Memoization in React.
import React, { useState, useCallback } from 'react';
const ParentComponent = () => {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, [setCount]);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<ChildComponent increment={increment} />
</div>
);
};
const ChildComponent = React.memo(({ increment }) => {
console.log('ChildComponent rendered');
return (
<div>
<button onClick={increment}>Increment from Child</button>
</div>
);
});
export default ParentComponent;
In the provided code, the ChildComponent rendering is controlled by the use of React.memo and useCallback. Here's an explanation of when the ChildComponent will and will not render:
When ChildComponent Will Render:
Initial Render: When the
ParentComponentis rendered for the first time, theChildComponentwill also render for the first time.Props Change: If the
incrementfunction passed as a prop toChildComponentchanges, it will trigger a re-render ofChildComponent. However, due to the use ofuseCallback,incrementwill only change ifsetCountchanges, which will not happen in this case.React.memo Dependencies Change: If the dependencies of
React.memochange,ChildComponentwill re-render. SinceReact.memois not provided with a custom comparison function in this code, it will use a shallow comparison of the props. If any prop changes, it will re-render.
When ChildComponent Will Not Render:
State Change in
ParentComponent: If the state of theParentComponentchanges but does not affect the props passed toChildComponent, theChildComponentwill not re-render. In this case, when thecountstate inParentComponentchanges,ChildComponentwill not re-render because theincrementfunction is memoized and does not change.Unchanged Props: As long as the props passed to
ChildComponentdo not change,React.memoensures thatChildComponentwill not re-render. Here, theincrementfunction remains the same due touseCallback, preventing unnecessary re-renders.
Code Analysis:
Initial Render: When
ParentComponentis rendered,ChildComponentwill render.Button Click in
ParentComponent: Clicking the "Increment" button inParentComponentwill update thecountstate. However, this does not affect theincrementfunction or other props passed toChildComponent, soChildComponentdoes not re-render.Button Click in
ChildComponent: Clicking the "Increment from Child" button inChildComponentwill also call theincrementfunction, updating thecountstate inParentComponent. Again, since this does not change the props passed toChildComponent, it does not re-render.
Conclusion:
The ChildComponent will only re-render if its props change. In this case, due to the use of useCallback to memoize the increment function, the increment function does not change when the ParentComponent re-renders, preventing unnecessary re-renders of ChildComponent. This optimization helps in improving performance by avoiding redundant renders.