componentWillRecieveProps is deprecated and getDerivedStateFromProps is being advocated to use.
But componentWillRecieveProps gets called when the props get changed but getDerivedStateFromProps is getting called on any state change even.
My requirement is to reset state on props change. So how would I get to know if the props really got changed.
I am not in favor of storing the props value in state as it would unnecessarily make the state bulkier and I still not have given state management(Redux or Context API) a thought
Please advise
how would I get to know if the props really got changed.
Compare previous prop with new prop.
For simplest use case, just use componentDidUpdate(), with prop comparing:
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
According to React Doc, it is OK to perform side effect or setState() inside componentDidUpdate().
And setState() can cause re-rendering, which affects component performance. When performance in this case is actually a thing, read on: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#when-to-use-derived-state
Related
Previously we used componentWillReceiveProps() to update a component on props change. Let's say have a component enable or disable an input field depending on some state in App.js
Now this is marked unsafe and
https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops
Explains several alternatives to use instead.
But I wonder why none of these mention the use of shouldComponentUpdate() for this case. I could use
shouldComponentUpdate(nextProp){
this.setState({
active: nextProp.active
});
return true;
}
To set the state of the component active which removes the disabled from an input field.
From reading the docs I couldn't understand why they suggest rather complicated memoization helpers or the componentDidUpdate lifecycle (which only provides previousProbs and thus state that's older than the current state).
Is there a reason not to do it like in my example?
shouldComponentUpdate is used in the case that a prop change is causing a re-render that you don't want - you may only care about certain props that affect the rendered view. You can manually inspect nextProps for changes to those specific props and decide to render or not.
You should not modify state (or anything else) inside of shouldComponentUpdate.
I know about PureComponent, but from the deep thought, I got confused about it.
ShouldComponentUpdate function is invoked when state or props are changed. So, we definitely know that something in state or props are changed if ShouldComponentUpdate is invoked. And those changes should be reflected in component view also. If state or props are not changed, shouldComponentUpdate is never called.
The PureComponent provides shallow comparison between old state or props and new state or props and if they are identical, it does not render. But we already know that the fact that shouldComponentUpdate is called means that new state or props are not same as old state or props.
Logically, I am confused about it so I got to post this question. Could you please give some advice for it?
NOTE: this is my understanding, so others please feel free to comment any issues/corrections
You've made an incorrect assumption in your question. You think for a plain React.Component that if nothing has changed in state/props then shouldComponentUpdate is never called and it won't re-render. That's not true, for example if a plain component's parent re-renders and that parent passes props to the child, the child will re-render too. Even if those prop values that it's passing are actually the same (you can test this by putting a console.log in the child's render() function). However, even though the child will re-render, nothing will actually change (in terms of the DOM) since the props are the same. So technically it did an unnecessary re-render.
In a plain component, shouldComponentUpdate always returns true (assuming you haven't explicitly defined it). So if the props/state are the same it will always re-render, it's just that if there aren't any pertinent differences, the DOM won't change in any way. However, in a PureComponent it will actually do a shallow comparison of the new state/props, and only trigger a re-render if they've changed. The idea is that it implements a shouldComponentUpdate method for you.
For components that don't often want to change, doing this shallow comparison (which is relatively quick and cheap) is better than constantly just re-rendering regardless of any changes. To summarise, pure components prevent unnecessary re-renders by doing comparisons of state/props before re-rendering, and making sure they're actually different.
I started to learn ReactJS I would like to know what are the scenario to use componentWillReceiveProps? what is the purpose for using it?
Currently i'm using props without it, is there any impact ?
In cases where you want to take action in child component in response to props change, componentWillReceiveProps was supposed to the right candidate. Example of it is when you have a user component which calls and API to fetch the user details based on an ID that is provided by its parent and anytime the prop ID changes, you would want to trigger the API call again and re-render the updated view.
However, componentWillReceiveProps is called on every parent re-render and not just prop change, so while you are using it, you must provide a conditional check between previous and currentProps like
componentWillReceiveProps(nextProps) {
if(nextProps.id !== this.props.id) {
//API call goes here
}
}
However from v16 onwards, its discouraged to use componentWillReceiveProps and instead its usage is split into componentDidUpdate which is where you can make API calls and getDerivedStateFromProps or memoized functions or key updates in order to make state change based on prop change.
Please check componentWillReceiveProps vs getDerivedStateFromProps for more details
If your component accept some props and if on change of that props you would like to do some business logic or state change, componentWillReceiveProps is the lifecycle method where this logic should go, as every time props changes componentWillReceiveProps is called.
componentWillReceiveProps(nextProps) {
// Check to see if the requestRefresh prop has changed
if (nextProps.requestRefresh !== this.props.requestRefresh) {
this.setState({loading: true}, this.updateData);
}
}
As far as my understanding goes, this lifecycle hook is called when a Component's properties are updated by the parent.
This piece of code checks if the requestRefresh property is different (one to update and one that it currently has)
Now what i dont understand is this , this.updateData);
why is this with the setState method. Please help me understand
Secondly where does prevState come from and which lifecycle hook can update it
the setState method can be called with a callback as its second parameter, mainly to handle operations which need to be done when the state is fully updated.
In your example this.updateData is the callback.
setState's first argument is also a function, with the signature (prevState, props) => stateChange, this is allowing you to get access to the previous state when performing updates.
You may want to check the official doc for further details :
https://reactjs.org/docs/react-component.html#setstate
The React maintainers discourage the use of componenetWillReceiveProps.
From the React docs:
It is recommended that you use the static getDerivedStateFromProps lifecycle instead of UNSAFE_componentWillReceiveProps. Learn more about this recommendation here.
To answer your question: prevstate is the previous state, so it is the state of your component before new props are received which in turn might chnage the new state. You can also hanlde prevstate in the static getDerivedStateFromProps method:
static getDerivedStateFromProps(nextProps, prevState)
getDerivedStateFromProps is invoked after a component is instantiated as well as when it receives new props. It should return an object to update state, or null to indicate that the new props do not require any state updates.
I have been reading the React docs and came across shouldComponentUpdate(). My understanding is that everytime setState() is called, a re-render of that component will be updated.
My question is that If the value to be updated is the SAME as the current state value, would this trigger a re-render event? or I would have to manually checks for the current value and value to be updated in shouldComponentUpdate()
The official React documentation states:
The default behavior is to re-render on every state change...
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
This means that by default, render() will be executed if any of a component's state or props values changes.
You can override this default behavior using shouldComponentUpdate(). Here's an example that only updates if a state value changes.
shouldComponentUpdate(nextProps, nextState) {
return this.state.someValue !== nextState.someValue;
}
Note: this example completely ignores props. So, any changes to props will not trigger render().
Adding more to #Jyothi's answer regarding implementing shouldComponentUpdate() to skip unnecessary re-renders, in React 15.3 they introduced a new concept PureComponent. From reactjs docs
The difference between them is that React.Component doesn’t implement
shouldComponentUpdate(), but React.PureComponent implements it with a
shallow prop and state comparison.
This allows to skip unnecessary calls of render in class components by just implementing PureComponent instead of the usual Component. There are a few caveats with PureComponent though, from the docs about React.PureComponent’s shouldComponentUpdate():
... only shallowly compares
the objects. If these contain complex data structures, it may produce
false-negatives for deeper differences.
... skips prop updates for the whole component subtree. Make sure all the
children components are also “pure”.
Usage of PureComponent can in some cases improve performance of your app. Moreover, it enforces you to keep state and props objects as simple as possible or even better, immutable, which might help simplify the app structure and make it cleaner.
I dont know if I understood your question correctly but react only re renders when there is difference between virtual dom and real dom.
And as Jyothi mentioned in his answer that render method will be called irrespective of the value passed in the set state function but rerendering will depend on what this render method returns.
In functional components, calling setState() with the equal value won't cause a rendering, while in a class component it does: https://dev.to/sunflower/reactjs-if-it-is-setting-a-state-with-the-same-value-will-the-component-be-re-rendered-5g24
Note that we're just talking about virtual (React) renderings here. Brower-rendering won't happen in any case - i.e. neither in the functional component nor in the class component - as long as the state (or to be more precise: the effective DOM) doesn't change.