React.memo () is a higher-order component (HOC) in React that can be used to optimize functional components. Memoization works by caching the result of a component’s render method and reusing it if the component is re-rendered with the same props. The purpose of memoization is to reduce unnecessary re-renders.
Introduction to React.memo()
React.memo() is a higher-order component (HOC) in React that can be used to optimize functional components. The purpose of memoization is to reduce unnecessary re-renders of components and improve the performance of your React application.
Memoization works by caching the result of a component’s render method and reusing it if the component is re-rendered with the same props. React.memo() provides a way to memoize functional components by comparing their props to determine if they need to be re-rendered.
By using React.memo(), you can avoid re-rendering components that haven’t changed, which can help to reduce the workload on your application and improve its performance.
When to use React.memo()
It’s important to use React.memo() carefully, as memoizing too many components will decrease performance by adding unnecessary overhead. Here are some best practices for deciding when to memoize a component:
- Memoize components that are expensive to render or have complex logic that doesn’t change frequently. like tables rows or product cards
- Memoize components that receive the same props may have different internal states or behavior.
- Memoize components that are part of a list of items that are re-rendered frequently, such as in a table or list.
Here are some examples of scenarios where memoization is useful:
- A component that displays the current date and time. This component doesn’t need to be re-rendered every time the parent component updates, since the date and time only change once per second.
- A component that displays a list of items that can be filtered or sorted. Memoizing this component can help to prevent unnecessary re-renders of each item in the list.
Just keep in mind you don’t need to overdo it if you decide to work on optimization and memorization
How to use React.memo()
Using React.memo() is simple and straightforward. Here’s a step-by-step guide to memoizing a functional component with React.memo():
Import React.memo() at the top of your file:
import React, { memo } from 'react';
Define your functional component as you normally would:
const MyComponent = ({ prop1, prop2 }) => {
// some logic here
return <div>{prop1} {prop2}</div>;
};
Memoize your component by wrapping it with React.memo():
const MemoizedComponent = memo(MyComponent);
Use your memoized component in your parent component as you normally would:
const ParentComponent = () => {
return (
<div>
<MemoizedComponent prop1="Hello" prop2="world" />
</div>
);
};
That’s it! Your functional component is now memoized with React.memo(), and it will only re-render when its props change. that was very simple usage of the memo
Important Bonus:
When passing a function as a prop to a memoized component, it’s important to make sure that the function is not re-created on every render of the parent component. Otherwise, the memoization will not work as expected, and the memoized component will be re-rendered unnecessarily.
To avoid this issue, you can use the useCallback
hook to memoize the function and prevent it from being re-created on every render of the parent component. Here’s an updated example that uses useCallback
to memoize the handleClick
function:
import React, { memo, useCallback } from 'react';
const ExpensiveComponent = ({ prop1, prop2, onClick }) => {
// some expensive computation or rendering logic here
const computedValue = Array.from({ length: 1000000 }, (_, i) => i + prop1).reduce((acc, val) => acc + val, 0);
return (
<div>
<p>Computed Value: {computedValue}</p>
<p>Prop1: {prop1}</p>
<p>Prop2: {prop2}</p>
<button onClick={onClick}>Click me</button>
</div>
);
};
// Memoize the component so it only re-renders when its props change
const MemoizedComponent = memo(ExpensiveComponent);
const ParentComponent = () => {
const [value, setValue] = React.useState('');
const handleChange = (event) => {
setValue(event.target.value);
};
const handleClick = useCallback(() => {
console.log('Button clicked!');
}, []);
return (
<div>
<input type="text" value={value} onChange={handleChange} />
<MemoizedComponent prop1={1000} prop2={value} onClick={handleClick} />
</div>
);
};
In this updated example, we’re using the useCallback
hook to memoize the handleClick
function. By wrapping the function in useCallback
and passing an empty dependency array ([]
), we’re ensuring that the function is only created once and not re-created on every render of the parent component.
With this approach, the memoized ExpensiveComponent
will only re-render when its props change, even if one of its props is a memoized function.
I hope this updated example helps to demonstrate how to pass memoized functions as props to memoized components.
Some Common mistake I see so many times
- As I mentioned earlier Memoizing too many components: Memoizing too many components can decrease performance by adding unnecessary overhead. Only memoize components that are expensive to render or have complex logic that doesn’t change frequently.
- Not passing all required props: React.memo() compares the props of a component to determine if it needs to be re-rendered. If you don’t pass all required props to a memoized component, it may not re-render when it should.
- Memoizing functions or objects with changing references: If you memoize a function or object passed as a prop to a memoized component, make sure that its reference doesn’t change on every render. If the reference changes, the memoization won’t work as expected.
Some best practices you can keep in mind
- Only memoize components that are expensive to render or have complex logic that doesn’t change frequently.
- Make sure to pass all required props to memoized components.
- If you need to memoize a function or object, make sure that its reference doesn’t change on every render. You can use the useCallback() hook to memoize functions and the useMemo() hook to memoize objects.
const expensiveObject = useMemo(() => {
// some expensive object creation logic here
return { /* ... */ };
}, [prop1, prop2]);
Conclusion and next steps
React.memo() is a powerful tool for optimizing your React applications and improving their performance. By memoizing components that are expensive to render or have complex logic, you can reduce unnecessary re-renders and improve the performance of your application. In this article, we’ve covered the basics of React.memo(), including when to use it and how to use it. We’ve also discussed common mistakes to avoid and best practices for using React.memo() with functions and objects.