Why shouldn't I use shouldComponentUpdate in ReactJS? - reactjs

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.

Related

React component re-render on "change in state or props" or "every state change", confusing official documentation

some more research from my side
( https://reactjs.org/docs/react-component.html#shouldcomponentupdate )
here it says
Use shouldComponentUpdate() to let React know if a component’s output
is not affected by the current change in state or props. The default
behavior is to re-render on every state change, and in the vast
majority of cases you should rely on the default behavior.
Here 1st sentence says change in state or props but 2nd sentence says every state change, which one is correct ?
or this is documentation bug ?
In this paragraph, the word 'state' is used in two different meanings. In the first one, it is used as a react-specific component property (as opposed to props). In the second one, it is used with a more generic meaning, like a state of an application.
Components in React re-render if either props or state changed, but you can control it using shouldComponentUpdate method by returning false if you want to prevent another re-render.

Is there a nested limit to react's change detection

I'm passing a complicated object with a lot of nested props. I have a a component that uses a deeply nested prop as
props.one.two[nth].three[nth].four = boolean
and a change in this boolean does not trigger a rerender in the component using it. I can see the bool update correctly in the dev tools and in logs, but render is not called until i perform some other action on this component (like typing) and then it rerenders to show the boolean update.
i just want to know if react's change detection has some kind of limit on how deeply nested it will detect.
According to the docs, the component will do a deep check on objects in order to determine if a rerender is required, unless that component is a React.PureComponent (for class compomnents) or uses React.memo (for function components), which will only do a shallow compare.
It might also not rerender if you are implementing shouldComponentUpdate and it returns false.

increase react application performance

I am currently developing a react redux based web application which displays large amount of data on the UI. When the data size increases, the frame per second decreases. Also, certain forms displaying components take longer and appear to be sluggish.
If someone could guide me on correct rendering method or some coding standards needed to be followed for such applications, it will be a great help.
-Thanks
I am currently checking whether my application uses react lifecycle components (explicitly by any other developer). I am also suspecting the way in which components are rendered.
Hello and welcome to StackOverflow!
Your question is very generic, so it's hard to pinpoint exactly how to resolve it.
I guess the first thing I'd do is take a look in chrome's performance tab in the developers tools. You can use it to profile you application and see what functions take the longest.
You can find helpful information here and here.
This will give you a good starting point.
As far as profiling a React application, you can take a look at React's Dev Tool profiler, more info can be found here.
You might also want to make sure to avoid the deprecated lifecycle functions, as they are known to cause performance issues. Those are:
componentWillMount
componentWillRecieveProps
componentWillUpdate
And make sure you perform all HTTP requests after components mount.
If everything fails, you should look into memoization techniques. Memoizing is basically saving the result of a function call in memory, so the next time your function is called with the same arguments, you don't recalculate the output. For that you can use React's builtin memo feature to memoize complete components, and a selector (like reselect) to memoize redux computations.
Please Check Prevent Unnecessary Rendering
All children in component re-renders when its props or state gets updated. This is the default behavior, and, since React updates only the relevant DOM nodes, this process is usually fast. However, there are certain cases where the component’s output stays the same regardless of whether the props have changed.
To alter the default implementation, you can use a lifecycle hook called shouldComponentUpdate(). This lifecycle hook doesn’t get invoked during the initial render, but only on subsequent re-renders. shouldComponentUpdate() is triggered when the props have changed and it returns true by default.
shouldComponentUpdate(nextProps, nextState) {
return true;
}
If you’re sure that your component doesn’t need to re-render regardless of whether the props have updated or not, you can return false to skip the rendering process.
class ListItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return false
}
render() {
// Let the new props flow, I am not rendering again.
}
}
Alternatively, if you need to update only when certain props are updated, you can do something like this:
class ListItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return nextProps.isFavourite != this.props.isFavourite;
}
...
}
For example here, we’re checking whether the current value of isFavourite has changed before each render (nextProps holds the new value of the prop) and if yes, the expression returns true. The component gets re-rendered. The changes in any other props won’t trigger a render() since we’re not comparing them in shouldComponentUpdate().
Attention Replacing ‘componentWillReceiveProps’ with ‘getDerivedStateFromProps’
With the release of React 16.3, some new lifecycle methods have been
introduced, and release of React 17 will deprecate some lifecycle
method.
You can find helpful information here

componentWillRecieveProps vs getDerivedStateFromProps

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

ReactJS, Calling setState with same parameter

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.

Resources