In your recent blog post you announced a "bugfix" for getDerivedStateFromProps():
getDerivedStateFromProps is now called every time a component is rendered, regardless of the cause of the update.
But in reality it broke a real-world library.
Now getDerivedStateFromProps() gets called on every re-render.
Suppose a component watches for a property change.
The recommended approach is to store the property value in state, like this.state.value.
Then, a user changes the input value, so both this.state.value and the property must be updated:
onChange = (event) => {
this.setState({ value: ... })
this.props.onChange(...)
}
static getDerivedStateFromProps(props, state) {
if (props.value !== state.value) {
return {
value: props.value
}
}
return null
}
The timeline is:
this.props.value and this.state.value are undefined.onChange(event) handler triggers and calls this.setState({ value: ... }).getDerivedStateFromProps() is called in the new React 16.4.props.value hasn't been updated yet, but state.value has, so the if condition triggers because props.value === undefined and state.value = .... Hence this.state.value gets reset by this if condition and becomes undefined (which is already a bug) because props are the "single source of truth" as per the official React recommendations.this.props.onChange(...) line executes which updates this.props.value which in turn calls getDerivedStateFromProps() again.if condition triggers again because props.value === ... and state.value = undefined and so this.state.value becomes ... again.In my case it actually breaks the phone number input component:
static getDerivedStateFromProps(props, state) {
if (props.value !== state.value) {
return {
value: props.value,
country: getCountryFromPhoneNumber(props.value)
}
}
return null
}
The design requirement is to let a user set value externally which in turn must update the country flag icon.
It worked in React 16.3.
In React 16.4 though getDerivedStateFromProps() gets called on each internal state update resulting in the country flag being reset every time a user types a character (because an incomplete phone number can't be a source of a country flag, e.g. USA and Canada both start with +1, not to mention the whole NANPA region).
You made a mistake in your code:
1) getDerivedStateFromProps is a static method, so you should not call methods on this like setState
2) You should return the changed state
The right way is:
static getDerivedStateFromProps(props, state) {
if (props.value !== state.value) {
return {
value: props.value
};
}
return null;
}
Please refer to https://github.com/facebook/react/issues/12898
@DavidBadura true, corrected the code samples. the issue still persists though.
Anyway, I'll rewrite my code in some way so that it works with 16.4.
Most helpful comment
You made a mistake in your code:
1)
getDerivedStateFromPropsis a static method, so you should not call methods onthislikesetState2) You should return the changed state
The right way is: