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.
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.
When will a React component using hooks re-render?
Let's assume the component:
Manages state with useState
Receives props from its parent
Will a re-render happen directly after the following events, and only at those points in time?
Component receives new props
state is updated
Related Question
Let's assume the component has several useState expressions and a user interaction causes multiple states to update.
Will the component re-render multiple times, once per state value that changed, or will it batch these related changes into one single re-render?
A component will re-render in the following cases considering it doesn't implement shouldComponentUpdate for class component, or is using React.memo for function
Component receives new props
state is updated
Context value is updated(if the component listenes to context change using useContext)
Parent component re-renders due to any of the above reasons
Let's assume the component has several useState expressions and a user
interaction causes multiple states to update.
Will the component re-render multiple times, once per state value that
changed, or will it batch these related changes into one single
re-render?
useState doesn't merge the updated values with previous ones but performs batching like setState and hence if multiple state updates are done together, one render take place.
Found this nice article on this topic. I'll add the summary in case someone needs a quick read.
What causes a render in react?
State modification
Component re-renders when its state is manipulated, simple as that. So, when you modify the state of your component it tends to re-renders with the new state value.
Passing Props
If the parent component has triggered a rerender all the child component will rerender too, generally you would only want the specific child components to rerender only if the component is consuming some props or the passed props are modified but that isn’t the case, it does not matter if the props are consumed, modified or not, the child components will re-render if the parent component has triggered a render.
Using the Context API
When modifying the state which is also the value passed to the context, the whole child components tree would get rerendered. Again doesn’t matter if the child component is consuming the context data or not, it will still rerender. The rerenders depend on the value passed to the provider but still, all the whole components tree would get rerendered.
Passing down references
In case of an object, array and, function comparison is based on references i.e. the exact memory location so, their comparison even though they seem equal yields false, in React Object.is method is used to compare the different values.
Example:
{}==={} //false
[]===[] //false
{a: 5}==={a: 5} //false
[1,2,3]===[1,2,3] //false
(when comparing the previous state to the new state, it returns false because they do not have the same reference. Only the value is the same)
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.
My current understanding is that a component mounts onto the DOM when it is needed to be seen or when the route requires that component. It will also render its child components. Does this mean that a component will be unmounted when you visit a route that doesn't have that component or whenever you visit any page that doesn't show the element that component produces? Thus, a component will need to be remounted every time it shows up on the DOM (outside of prop and state changes), correct?
During the VirtualDOM Reconciliation if a component existed but no longer will, the component is considered unmounted and given a chance to clean up (via componentWillUnmount).
The reverse is true, during the reconciliation, if a component didn't exist, but now does, the component is considered ready to mount, and given a chance to prep itself (constructor / componentWillMount)
When tearing down a tree, old DOM nodes are destroyed. Component
instances receive componentWillUnmount(). When building up a new tree,
new DOM nodes are inserted into the DOM. Component instances receive
componentWillMount() and then componentDidMount(). Any state
associated with the old tree is lost.
https://facebook.github.io/react/docs/reconciliation.html
That particular page is well worth a read if you haven't already. It also explains why key is pretty important for repeated elements.
Component will be mounted on DOM only when it needs to be rendered. If you change the route or refresh the page or you want to render your component on specific events (eg onClick show/hide the component) then componentWillUnmount() will be called and component will be removed from DOM
Simply put, when a component has mounted, componentDidMount() is called, when the component is about to unmount, componentWillUnmount() is called. During re-rendering, if the component is neither to be mounted nor unmounted, neither of the aforementioned methods will be called. Instead, simply the changes made to the code of the component will be updated.
Please remember that most React apps are Single Page Apps which means they only update the existing page, they don't create any new page like page1.html, page2.html. What happens is that React unmounts unnecessary components from page1 and mounts necessary components described in page2 such that it looks like page2. But it doesn't really "leave page1.html" and take you to a whole new page called page2.html. All it does is simply pop and push components in one canvas or page. In other words, React "brings" page2 into page1. But the canvas remains the same(page1).
So, the answer to your question is, yes, a component will unmount and remount when its removed or added to the page.
I would say a component mount onto the DOM only if it's used via another component, including a Router component. Don't think of routers as special elements/things in React. They're like other components and they do a matching between current URL and the patterns they have to decide which component should be rendered via the render() function of Router. Whenever there is a change of URL, the router picks the new component to render and does rendering via render() function.
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().