Javascript: Calling setState in componentDidUpdate

Created on 30 Jul 2018  路  10Comments  路  Source: airbnb/javascript

It might be worth revisiting react/no-did-update-set-state.

Now that componentWillReceiveProps() is being deprecated, componentDidUpdate() is the only "safe" way to detect changes in props and set state accordingly.

The React docs say calling setState() in componentDidUpdate() is permitted, albeit with caveats.

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you鈥檒l cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance.

Most helpful comment

Polluting state with previous props/state really sucks.

All 10 comments

getDerivedStateFromProps?

The new lifecycle method getDerivedStateFromProps is not a perfect replacement for componentWillReceiveProps as it does not provide access to prevProps.

It would be reasonable, in React 16 and later, to modify the rule's behavior so that it does not warn on "safe" usages of setState.

(this would need to be done in eslint-plugin-react, however, not here)

The new lifecycle method getDerivedStateFromProps is not a perfect replacement for componentWillReceiveProps as it does not provide access to prevProps.

@dlwalsh, you may want to check this technique from the official React blog but I would suggest to read the entire article -- maybe you can completely avoid usage of getDerivedStateFromProps :)

Polluting state with previous props/state really sucks.

@dlwalsh yep it sucks, but it's inevitable in some cases. How do you change the state of a component reacting from a change from react-router that pass match through props?

componentDidUpdate is the appropriate place to put asynchronous server updates so this warning is patently false, misleading and confusing.

This rule should be removed or modified to check for a condition. The React docs themselves explain how to safely update the state within componentDidUpdate:

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition
React Docs

FWIW, I like to outsource lifecycle method work to (other) named methods in order to ensure they remain segmented by concern. This rule only looks for this.setState in the body of the lifecycle method, so you can do this and get no warning (regardless of whether there _should_ be):

 componentDidUpdate(lastProps: Props) {
    this.updateCursorSuggestionIfNeeded(lastProps.data)
  }

  updateCursorSuggestionIfNeeded(lastData: WhateverData) {
    const { data } = this.props
    if (needsUpdate(data, lastData)) {
      // no way for linter to warn here, with or without the above condition
      this.setState(updatedStateForData(data))
    }
  }

Keeps things neat and negates the (in _this_ case, unnecessary) lint warning.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

progre picture progre  路  3Comments

weihongyu12 picture weihongyu12  路  3Comments

xgqfrms-GitHub picture xgqfrms-GitHub  路  3Comments

olalonde picture olalonde  路  3Comments

stephenkingsley picture stephenkingsley  路  3Comments