Let's first understand how React re-renders
State change:
When a state change it re-render its component, it also re-render all of its descendants components.
Let's understand by an example
export default function App() {
return (
<div className="app">
<Counter />
</div>
);
}
const Counter = () => {
const [count, setCount] = useState(0);
const handleCount = () => {
setCount(count + 1);
};
return (
<div className="counter">
<Display count={count} />
<button onClick={handleCount}>Count</button>
</div>
);
};
const Display = ({ count }) => {
return <div>{count}</div>;
};
So I'm not going to bore you to read every lines of the code. Here are highlights:
- The main component is
<App />
which renders<Counter />
and which renders<Display />
, TheCounter
hascount
state and a button which triggershandleCount
on click.
Whenever the count
state change, the Counter
component will re-render and it re-renders all of its descendents component.
But why App
component didn't re-render?
The answer is very simple the count
state is defined inside the Counter
component and we are updating the count
state, so it will re-render that component and its descendants.
After understanding how component re-renders in React, let's take a look at when to use memo() in React.
export default function App() {
const [list] = useState(USERS); // List of users
const [color, setColor] = useState("#fdd3c2");
const handleColor = () => {
const randomColor = getRandomColor();
setColor(randomColor);
};
return (
<div style={{ backgroundColor: color }} className="App">
<List list={list} />
<Button handleColor={handleColor} color={color} />
</div>
);
}
const Button = ({ color, handleColor }) => {
return (
<button className="button" onClick={handleColor}>
{color}
</button>
);
};
const List = ({ list }) => {
return (
<ul>
{list.map((item) => {
return <li key={item.id}>{item.name}</li>;
})}
</ul>
);
};
Here are highlights:
- We have two state named list and color in
App
component. TheApp
component renders two componentsList
andButton
- The list state is passing to
List
component through prop and render the list insideList
component. - The color state is passing to
Button
component through prop.
so when the user clicks on button the color state is changed, because of color state defined inside App
component. The App
component re-render and it also re-render both List
and Button
component but here is the problem, why we want to re-render List component even though list state hasn't changed and also we are not passing color as a prop to right. It might be a performance problem if the list is too long.
We can wrap the whole List component inside memo() to avoid unneccesary re-render of component if the prop hasn't changed
...
const List = memo(({ list }) => {
console.log("Re-render List")
return (
<ul>
{list.map((item) => {
return <li key={item.id}>{item.name}</li>;
})}
</ul>
);
});
Now, If we clicks on button to change the color, the <List>
will not re-render because the list props has not changed and we wrapped the <List>
component inside memo().
What does the mean of memo?
Memo means memoization (memorization), it is a cache technique in which react will re-use the previous snapshot if the none of props have changed rather than going to generating a brand new.
By this technique we can save unwanted re-renders of component if the props have not changed.
NOTE:
- This is technique will not useful in most of scenerios, we must not have to wrap all of components inside memo()
- This technique will not works on if the props are objects or function because objects or functions are recreate everytime on re-render. To use memo() techniques on objects and functions we can wrap objects and functions inside useMemo() and useCallback respectively
Top comments (1)
I like your article, helpful info, keep up the good work 👍