Calling setState in componentDidUpdate
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’ll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance.
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.
Above example is typescript, right?. I'd like to know how to use componentDidUpdate from componentWillReceiveProps in Javascript.