In React, changes to a component's state triggers a re-render of the entire component tree. This means that not only does the render function of the component get called, all its subsequent child-components will re-render as well, even when their props have not changed.
When your application is large, unnecessary re-rendering is expensive and reduces performance. To avoid this, we can look at to a concept called Memoization.
Memoization
Wikipedia defines Memoization to be:
... an optimisation technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.
This means that it is a technique that executes a pure function once, stores the results, and if the function is called again with the same arguments, it returns the previously saved results without executing the function again (because we assume the outcome is the same).
In other words, it is a away to lower the function's time cost in exchange for space cost; that is, memoized functions become optimised for speed in exchange for a higher use of computer memory space.
React.memo in action
In the context of React, the functions are our React (pure) components, and the arguments are our props. React.memo
is a HOC built of the concept of memoization and tells the component to only re-render when its props change.
Let's create a component that has an input field and a button to add a new user:
const App = () => {
const [value, setValue] = useState("");
const [names, setNames] = useState(["Avery", "Bain"]);
const handleInput = (e) => {
setValue(e.target.value)
}
const handleAddUser = () => {
const updatedArray = names.push(value);
setNames(updatedArray);
}
console.log('render App');
return (
<div>
<input value={value} onChange={handleInput} />
<button onClick={handleAddUser}>
Add User
</button>
<List list={names} />
</div>
)
};
const List = ({list}) => {
console.log('render List');
return (
<ul>
{list.map((name, key) => <li>{name}</li>)};
</ul>
)
};
export default App;
In here, the component gets re-rendered every time someone types into the input field (before adding a user), because value
changes. The problem is, List
also gets re-rendered, even when its props remains the same.
// when user types one char into input
render App
render List
With React.memo
, we can optimise rendering behaviour by telling List to only re-render when its props changes:
import { memo } from 'React';
const List = memo(({list}) => {
console.log('render List');
return (
<ul>
{list.map((name, key) => <li>{name}</li>)};
</ul>
)
});
Now, when we type into the input field, only App
is re-rendered because it is the only component affected by the state change.
// when user types one char into input
render App
// when a new user is added
render App
render List
To recap
By default, React re-renders components when its state changes. This means that a child component will also render as a result of a state change in its parent component, even when its props remain the same.
React's memo API optimises rendering behaviour by re-rendering components only when their props change. Thoughts? Let me know in the comments below! 👇
Top comments (2)
Hi hmintoh, great post :) react memo is so usefull !
Though, I think you've made a mistake in the first code block :
You wrote:
instead of
and
instead of
fixed, thank you for flagging @calag4n !