Table of contents
Backstory
Hey there! So, I recently faced an issue in my React project that I want to share with you.
I had a parent component that contained two child components - Header and List. The Header component had a search input field, where the search value was stored in the parent component. On the other hand, the List component was responsible for displaying a list of 50 users' data at a time, with each user represented inside a card.
The search input field was used to filter the displayed list, but when I started typing in the search field, there was a noticeable delay in the words being typed. This was causing a bad user experience, and I knew I had to fix it.
At first, I thought that there might be some debounce method implemented somewhere, which was causing the delay. But upon further inspection, I didn't find any such method in the code. So, I tried moving the search input field to the Header component, which did resolve the lagging issue. However, I didn't want to shift the search state inside the header component, as it was better for it to remain in the parent component to be used to call an API to filter out the data.
After reading through some forums, I learned that the lag could be caused by the List component being re-rendered every time the parent component was re-rendered due to a state change. To confirm this, I used the React Profiler present in Chrome and observed that the ListItem component was getting re-rendered every time I typed something in the search field.
Resolution
Memoization in React
To fix this problem, I memoized the ListItem component using memo().
So, what is memoization? Memoization is a technique where the output of a function is cached based on its input. In the context of React, memoization refers to caching the result of a component's rendering based on its props. If the props of the component haven't changed, React will reuse the cached result instead of re-rendering the component.
Memoization is particularly useful when working with complex or expensive components that take a lot of time to render. By memoizing these components, you can significantly improve the performance of your application. It's important to note that memoization only works for functional components and not class components.
When we memoize a component using memo()
, the component will only re-render if its props or state have changed. Memoization by default only works for props that are primitives. If the props passed to the component are functions or objects that are created inside the parent component, they will be recreated on every render, causing the memoization to be ineffective.
This is where the useCallback
and useMemo
hooks come in. These hooks can be used to memoize functions and objects that are used as props in a memoized component, so that they are only recreated if their dependencies change.
Now let's see how to memoize a React component in practice. React provides a built-in function called memo()
that we can use to memoize a component. Here's an example:
import React, { memo, useCallback, useMemo } from 'react';
const ParentComponent= () => {
const [query, setQuery] = useState('')
const handleClick = useCallback((value) => {
setQuery(value);
}, []);
const processedData = useMemo(() => {
// some expensive computation using data
return processedData;
}, [query]);
return <>
<HeaderComponent />
<BigListComponent handleClick={handleClick}
processedData={processedData} />
</>
};
const HeaderComponent= (props) => {
// render component
};
// Memoizes component
const BigListComponent = memo((props) => {
// render component
});
Demo of React memo:
In summary, if you're facing a similar issue where there's a delay in updating the UI due to a large number of unnecessary re-renders, memoizing the components can be a useful solution. It's always a good practice to keep an eye on the performance of your React application using tools like React Profiler to identify and fix any performance-related issues.
P.S. You should also consider using React virtualization for big lists, to improve the performance.