Improving your website's performance is a critical step toward enhancing user experience and ensuring a solid, responsive interface. If you're working on a React or Next.js project with some resource-intensive components, it's natural to worry about their impact on performance. This is where memoization in React comes in—it helps speed up these 'expensive' components, leading to a smoother experience for your users.
In this article, I'll cover memoization and introduce React hooks that can optimize your app's performance, like useMemo()
, useCallback()
, and the React.memo
Higher-Order Component (HOC). Let’s dive in!
What is Memoization in React?
Memoization is a technique used to speed up programs by caching the results of computational tasks—such as function calls—so that if the same inputs are provided again, the cached result is returned instead of re-computing it.
The useMemo
Hook: Caching Results in React
useMemo
is a hook which cache or memoize the result of function between re-rendering or updating component.
so by using this hook you can cache result of a function which is in your component and when next re-rendering your componet will use cach result if input of that function is not changed.
How to Implement useMemo
:
useMemo
is a hook that takes your unoptimized function as a callback and a list of dependencies. React then decides when to call this function either during the initial rendering or on subsequent re-renders.
Initial Rendering: During the initial render, React calls the
useMemo
function to calculate and store the result of the callback function you provided.Re-rendering: On re-renders, React calls
useMemo
to check if the dependencies have changed. If the dependencies have not changed, React reuses the cached value stored during the last render. However, if the dependencies have changed,useMemo
calls the callback function again to re-calculate and store the updated value in the cache.
Example:
import React, { useMemo } from 'react';
const MyComponent = ({ number }) => {
const squaredNumber = useMemo(() => number * number, [number]);
return <div>Squared Number: {squaredNumber}</div>;
};
squaredNumber is calculated only when number changes. useMemo
caches this calculation, so it won’t recompute unnecessarily on every render.
The useCallback Hook: Caching Function Definitions
useCallback is a hook that caches, or memoizes, the definition of a function between component re-renders or updates.
By using this hook, you can store the definition of a function across re-renders, so React will reuse this cached version as long as the function’s dependencies haven’t changed.
How to Implement useCallback
:
useCallback
is a hook that takes a function (as a callback) and a list of dependencies. React then decides when to return (not call) this function—either during the initial rendering or on subsequent re-renders.
Initial Rendering: During the initial render, React calls
useCallback
to store the function you passed as a callback.Re-rendering: On re-renders, React calls
useCallback
to check if the dependencies have changed. If the dependencies have not changed, React reuses the cached function stored during the last render. If the dependencies have changed,useCallback
will store and return the updated function.
Example:
import React, { useState, useCallback } from 'react';
const MyComponent = () => {
const [count, setCount] = useState(0);
const [multiplier, setMultiplier] = useState(2);
// Memoize the callback with `count` as a dependency
const calculate = useCallback(() => {
console.log("Calculating:", count * multiplier);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<p>Multiplier: {multiplier}</p>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<button onClick={() => setMultiplier(multiplier + 1)}>Increment Multiplier</button>
<button onClick={calculate}>Calculate</button>
</div>
);
};
export default MyComponent;
The React.memo
Function: Preventing Unnecessary Re-renders
As you may know, when you have a parent component and child components, any update to the parent’s state or props will cause all its child components to re-render. In small projects, this might not be an issue, but in larger and more complex applications, unnecessary re-renders of child components can impact performance. To address this, React provides the memo()
function.
The memo
(or React.memo
) function allows you to wrap a component to prevent it from re-rendering when the parent updates. The wrapped component will only re-render if its own props or state change.
When you first call memo()
on a component, React renders and caches the component. On subsequent renders, React will use this cached version as long as the component’s props and state haven’t changed. Keep in mind that memo()
only avoids re-renders for unchanged props and state—once they do change, memo()
re-renders and updates the cached component accordingly.
How to Implement React.memo
:
To implement memo in your component, simply wrap the component you want to prevent from unnecessary re-rendering with memo()
or React.memo
():
import React from 'react';
const MyComponent = ({ data }) => {
return <div>{data.value}</div>;
};
export default React.memo(MyComponent);
Note:
If you pass an object as a prop to a component wrapped in memo()
, the component will still re-render on every update, even if the object hasn’t changed. This happens because React uses Object.is to compare previous and current props. While Object.is(3, 3) returns true, Object.is({}, {}) returns false, since two different object references are never considered equal.
To avoid this, you can use useMemo
to cache the object and keep the same reference across renders:
import React, { useMemo } from 'react';
import MyComponent from './MyComponent';
const ParentComponent = () => {
const data = useMemo(() => ({ value: "Hello" }), []); // Cached object reference
return <MyComponent data={data} />;
};
In this example, useMemo
ensures the data object has the same reference, preventing unnecessary re-renders of MyComponent.
Thank you for reading my article! If you’d like to learn more about Next.js, React, JavaScript, and more, feel free to follow my website: saeed-niyabati.ir. Don’t hesitate to reach out with any questions. See you next time!
Top comments (0)