The documents have the following to say about forceUpdate:
Calling forceUpdate() will cause render() to be called on the
component, skipping shouldComponentUpdate(). This will trigger the
normal lifecycle methods for child components, including the
shouldComponentUpdate() method of each child. React will still only
update the DOM if the markup changes.
https://reactjs.org/docs/react-component.html#forceupdate
Does this mean that children of the component also have their render function called?
It will "re-render" every child that does not return false inside of its shouldComponentUpdate method, however note that re-rendering !== re-drawing, it will just cause React's diffing algorithm to run.
And only, if the diffing algorithm sees a difference in the current version of the virtual DOM compared to the previous version of the virtual DOM will the specific "changed" part of the UI get re-drawn on the screen.
Related
I am beginner in React JS. I came across React.memo() a HOC component that basically only re-renders the component if the component execution results are different from its previous result which it memonizes. But why do we need to use it if there is already a concept of Virtual DOM?
Like doesn't the Virtual DOM concept also do the same thing that is not re-rendering the component if the resultant virtual DOM is the same as the main DOM?
If I get it correctly aren't both follow same concept functionality wise?
React rendering happens at multiple levels. The virtual DOM kicks in at React<->Browser, but using React.memo() can reduce the amount of times that your React code needs to be run. In short:
Virtual DOM: Reduces HTML element creation/edits
React.memo(): Reduce React component re-renders (before even touching HTML)
For it's own - yes, similar to Virtual DOM. But from documentation:
[The memo()] component will usually not be re-rendered when its parent component is re-rendered. […] memoization is only a performance optimization. […] React normally re-renders a component whenever its parent re-renders.
So in other words you can use React.memo() to optimize component if you know that even if parent has changed, this component will not change.
React will execute your function component, compare it to the dom and will update if there are changes. If you use React.memo() your function component will not be executed again and it won't be compared to the dom.
So if you have a calculation in your function compoent that takes one second, without React.memo() it will run this calculation again.
Lately I've been working on a React app.
In one of the pages which was suffering from slow load, I discovered there was some updates to state, and those variables where not meant to be shown to end user, and they were there to be checked later when some event was raised.
Since those were arrays, I mutating the state directly and event without "setState"ing it (I know mutating the variable is not recommended at all!).
Later when the Event was raised, state variable had correct data and since redundant "setState"s where removed, the page had a significant speed boost and the problem was solved.
Anyone has any similar experiences with "setState" in react?
What do you think about this?
...I discovered there was some updates to state, and those variables where not meant to be shown to end user...
Then they shouldn't be part of state, they should just be properties on the instance (in a class-based component, which I assume you're using; variables you close over in a functional component). state should only contain things that, when changed, cause a re-render. For that reason, you should only change them via setState, so the render is triggered. You're getting away with breaking the rule because what you're changing isn't related to rendering.
Never mutate the state object (or any objects it refers to) directly. But you can mutate non-state properties (or things you close over), that's fine.
If you need those variables to be stored in actual state but them does not have to trigger a render you probably need to implement shouldComponentUpdate lyfecycle callback:
shouldComponentUpdate(nextProps, nextState) {
return nextState.myPropertyThatTriggersRender != this.state.myPropertyThatTriggersRender;
}
Doing that, if all your state's properties that trigger render are checked, other state properties won't trigger a render. But will be still available in state object.
In order to improve performances, you can implement the same check on the child elements (if they are components) that are going to be rendered.
shouldComponentUpdate(nextProps, nextState) {
return nextProps.myPropThatTriggersRender != this.props.myPropThatTriggersRender;
}
From React's DOC:
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.
How does react create a new virtual DOM for a component when it is updated using a setState() call, even when shouldComponentUpdate() returns false?
Does react create the virtual DOM again for all components, even for components on which setState() was not called? I mean suppose setState() is called on child component, does react a new virtual DOM for the parent component also?
Does react create virtual dom even when shouldComponentUpdate returns false ?
No it does not. If shouldComponentUpdate returns false, the re-render for that particular component and its children is not done.
Does react create virtual dom again for all components, even for component on which setstate is not called.
It will create for those components (and its children) whose state or props have changed. But that does not necessarily mean actual DOM update will happen. Also as mentioned above if any of those components return false from shouldComponentUpdate, re-render is stopped for that component and its child trees.
I mean suppose setstate is called on child component, does react new virtual d for parent component also
No. Parent causes child re-renders, not the reverse. React only re-renders that subtree. Not its roots.
That said, a re-render (Virtual DOM creation) does not always mean DOM change. If previous virtual DOM & new virtual DOM for a subtree is same, the actual DOM is left untouched.
React has explained this using a very clear and concise example in their docs.
I want to know, what are events, that cause React component to re-render.
I couldn't find full list anywhere, it'd be great if someone writes the list of events, that cause React component to re-render.
I always find the following reference website helpful.
http://reactcheatsheet.com/
Filter by lifecycle events, and you can see the places where setState will trigger a rerender.
__
Update: you now have to filter by "misc"
React component is re-rendered when setState() is called or when props change. You can also force re-render with forceUpdate()
https://reactjs.org/docs/react-component.html#forceupdate
By default, when your component's state or props change, your
component will re-render. However, if these change implicitly (eg:
data deep within an object changes without changing the object itself)
or if your render() method depends on some other data, you can tell
React that it needs to re-run render() by calling forceUpdate().
I have a parent class component that has a function in componentWillMount that loops through a list of strings and creates an element for each one and finally setState on this.state.map. Each child element receives a prop which is a state in parent called this.state[element].
The reason I put these elements into this.state.map was because I can change things in (some) upper components without having to re-render the array each time (which is painfully slow) and I didn't want to use shouldComponentUpdate. Plus in the future I can just quickly change elements by toggling different map states.
The problem is, when the parent this.state[element] (that's passed to child as props in the initial componentWillMount) changes, it doesn't update the props for the child. Parent state does change though.
Is this a legit way to do this?
I'm sorry I didn't provide code sample. It's just such a mess at the moment.
Only ReactDOM.render (and serverside rendering etc.), setState, or forceUpdate, will cause your children to re-render. If you are just mutating the state object, React is unaware of this, and will not re-render. Anyways, mutating the state not through setState is not valid, and you should try to keep your state as immutable as possible. In order for you to see the changes in your children, you need to use setState to update this.state[element].
From the React docs:
Notes:
NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.