I have a React Native component where I want to prevent the render() method from being called.
class A extends Component {
shouldComponentUpdate() {
return false;
}
render() {
return(...)
}
}
Returning false in shouldComponentUpdate should prevent render() from being called, but it doesn't. Is there something I'm doing wrong?
Indeed, it prevents a rerender but not the initial rendering. This is documented here.
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.
and
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.
Hence, if you return false, then you only prevent a rerendering on state changes.
you can try use hooks useMemo or useCallback https://reactjs.org/docs/hooks-reference.html
to choose what you want to update
Related
I have the following problem:
I got an App (A) and a lot of children (B, C, etc).
Now I would like to pass a value from B to C but without any rerender of the whole App. How is this possible?
A (Parent)
|---- B (Child)
|---- C (Child)
|---- D (Child)
|---- E (Child)
|---- F (Child)
I tried to use useContext or a simple callback but in each case the state is hold in A, which, by change makes my whole App to rerender. Any Idea on how to make ii in a proper way?
You can use
shouldComponentUpdate
to avoid this type of scenario. It works for both props and state.
shouldComponentUpdate(nextProps, nextState) {
return this.props.somevalue != nextProps.somevalue;
}
Check if there is any new props passed to the child. If not then the component wont re-render. But avoid using too many children and come up with a better design structure.
Edit:
You can use
PureComponent
as it implements shouldComponentUpdate by default. As mentioned in the doc:
React.PureComponent is similar to React.Component. The difference
between them is that React.Component doesn’t implement
shouldComponentUpdate(), but React.PureComponent implements it with a
shallow prop and state comparison.
If your React component’s render() function renders the same result
given the same props and state, you can use React.PureComponent for a
performance boost in some cases.
The default behavior in React is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior. But when you want to block the re-render of component when the state change and some value from state are passed to child component as props you can take advantage of shouldComponentUpdate
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.
Lean more here
To block the re-render you should should perform a check in the shouldComponentUpdate to ensure that the previous props and the current one aren't the same. If they are the same. you block the re-render by return false and if they are different you return true which will trigger the re-render.
Or you can use memo
You can use React.memo(component)
This is saved your component from unusual renders.
read this one https://reactjs.org/docs/hooks-reference.html#usememo
I have a functional component which has has a connection to an object in my Redux store. To avoid re-renders when the object has changed I added React.memo, however, this didn't avoid the re-renders. My Memo looks something like this:
const MemoizedRadio = React.memo(Radio, (prevProps, nextProps) => {
if (prevProps.selected !== nextProps.selected) {
return false;
}
return true;
});
const mapStateToProps = state => ({
nodes: state.canvas.elements.nodes
});
export default connect(mapStateToProps)(MemoizedRadio);
I would expect this component to not re-render if the nodes object has changed, but it does.
When I rewrite my component to a class component and add a shouldComponentUpdate the re-render will be prevented as expected. The shouldComponentUpdate looks as followed:
shouldComponentUpdate(nextProps) {
if (this.props.selected !== nextProps.selected) {
return true;
}
return false;
}
I thought that React.memo acted the same as shouldComponentUpdate but this does not seem to be the case. The React.memo implementation does always re-render when the reference to the nodes object changes while the shouldComponentUpdate implementation prevents the re-render as expected.
Can anyone explain this behaviour?
You are using React.memo correctly, the problem is that you are using connect an HOC to connect class based components to the store. Instead of using HOC you should use useDispatch and useSelector
If I have a react component, and I just set its class variables, ie
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.numberElements = 20;
this.color = 'red';
}
render() {
...
}
}
Can't I just call this.forceUpdate() to issue a re-render (whenever I update my class variables) instead of maintaining a state and calling setState?. Or is it bad to do that, and if so, why?
forceUpdate() is actually useful in scenarios like the one you're describing.
From the docs:
By default, when your component’s state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate().
The caveat, however, is that it will skip shouldComponentUpdate(), so you're not getting the optimization benefit.
Also, using forceUpdate() "bypasses" the proper lifecycle, making your code less straight-forward and possibly harder to understand and maintain.
It is therefore recommended to use state and props when possible.
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().
The issue I've encountered is an infinite loop.
I have this state:
this.state = {
apiData: [],
pageNum: 1,
isLoadingList: 0,
search: "",
layout: "list"
}
I have a function that fetch data from an API:
fetchApi(){
fetch("www.api.com", ...)
}
And once the data fetched, it saves everything in apiData (this.state.apiData)
The thing I'm trying to do is to call that function, "fetchApi()", when "this.state.search" changes. If I do that using Lifecycle's components like componentDidUpdate(), ... it will create an infinite loop as apiData is a state too (the changes made to this.state.apiData will trigger Lifecycle's components related to states again, and again, and ...).
So I would like to track ONLY this.state.search and when it changes it calls the function "fetchApi()" that change this.state.apiData value.
I might trying to do something that is wrong and shouldn't be done like that, so any ideas to do the same thing but in a different way are welcome.
Thanks!
Use shouldComponentUpdate
shouldComponentUpdate: function(nextProps, nextState) {
return this.state.search !== nextState.state.search;
}
shouldComponentUpdate is meant to be used like this:
shouldComponentUpdate(nextProps, nextState) {
const currentState = this.state
return currentState.search.id !== nextState.search.id
}
When you update state of a component, it will trigger these methods in this order:
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
shouldComponentUpdate is called just after the state change (with setState), and should return a boolean, React will not call the next methods if false is returned.
You should NEVER call setState from the shouldComponentUpdate method. It's here to prevent unneeded view calculation.
Your infinite loop, if you defined shouldComponentUpdate correctly, does not come from the StateChange hooks chain.
A custom implementation for the shouldComponentUpdate() method as part of the React component lifecycle is not required.
I understand it's a boolean function that determines whether render() will be called upon changes in component props and state, and there are mixins like PureRenderMixin which implements the shouldComponentUpdate()
If no custom implementation nor mixins are provided. What's the default implementation and behavior?
As of React v0.13 and v0.14 the default implementation equals to null and as per this logic:
var shouldUpdate =
this._pendingForceUpdate ||
!inst.shouldComponentUpdate ||
inst.shouldComponentUpdate(nextProps, nextState, nextContext);
the component is updated every render cycle (since !inst.shouldComponentUpdate evaluates to true).
Defaults to true.
The default behaviour is to re-render on every state change, and in the vast majority of cases, you should rely on the default behaviour.
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.
Given the documentation React Docs the default is true:
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true.