Setting the scene
Picture a parent component with some child components and we are updating the parent’s state. What will happen?
|
|
|
|
Note that I have added
console.log
to each component in order to track when they are being rendered.
So how does it renders?
Everything renders properly and after clicking on the Increment button 3 times, the result is as expected.
Now analyzing at the console output, we can see that the <Parent>
was rendered 4 times. Most certainly when the value of count was 0, 1, 2, 3.
But why did the <ChildButton>
had to be rendered 4 times also? Isn’t that a waste for resources since the <ChildButton>
component didn’t change in any way?
While with minor components these additional rendering are harmless, it can affect the application’s performance when more complex components are being utilized.
Avoiding unnecessary re-rendering
We can use memo
to tell React to skip re-rendering a component unless it’s props have changed. Here’s how it’s done:
|
|
Let’s now run our application again and do the same test.
It looks like nothing has changed! Why?
Change detection in React
Well it might look that nothing has changed but from a JavaScript point of view, everything has changed!
In our <Parent>
component, we are passing down props as follow:
|
|
React will do simple equality checks for change detection. Consider this:
|
|
As you can see above, an empty function when compared using ===
to another similar empty function gives false
.
So from React’s perspective, it looks like the props did change, so a re-render is triggered.
useCallback
to the rescue
So how can we tell React that the onClick
prop hasn’t changed?
We can use useCallback
to do just that!
|
|
The first parameter of useCallback
is the function and the second parameter is the dependency list.
What is the dependency list? It is all variables (or const
) used inside the function callback but declared in the component (including props).
Then why not include setCount
? It is definitely declared in the component and used inside the callback function! Yes you can include setCount
in the dependency list, but it will not affect the callback in any way since settors are stable across renders and never triggers change detection in React.
Result after using proper hooks
Again, the button is pressed thrice and voila!
You can now clearly see how unnecessary re-rendering has been avoided.
If you are more curious about React hooks, read about useMemo and useEffect from the official React docs