React Memoization — useCallback, useMemo and React.memo
Real Examples of when to use useCallback, useMemo, and React.memo
In computing, memoization is an optimization 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.
React offers hooks and HOC(High Order Component) that perform that technique so we can improve our application performance. They are useCallback and useMemo which are React Hooks and React.memo which is a HOC.
useCallback
useCallback
is a React hook that creates a memoized callback. The hook accepts two parameters: a function that needs to be memoized, and a list of dependencies that determine when the memoized function should be updated. When the dependencies remain the same, the hook will return the same function; this helps to reduce unnecessary re-renders.
In this example, we have a form that allows users to enter their name and email. When the form is submitted, it sends the data to the backend. To prevent the form from re-rendering unnecessarily, we use the useCallback
hook to memoize the function that is called on form submit.
import React, { useState, useCallback } from "react";
const RegisterClient = () => {
const [name, setName] = useState<string>("");
const [email, setEmail] = useState<string>("");
const handleSubmit = useCallback(() => {
// PERFORM SOME ACTION WITH THESE DATA
console.log(`Send these data Name: ${name}, Email: ${email}`);
}, [name, email]);
return (
<form>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit" onClick={handleSubmit}>
Send
</button>
</form>
);
};
export default RegisterClient;
Note that by including the name and email variables in the dependency array of the useCallback
hook. This will cause the function to only be re-created if either of these values changes, and will stop unneeded re-renders.
useMemo
useMemo
is a hook that lets you cache the value of a function that is expensive to compute. The useMemo
hook takes two arguments: a function that returns the value to be cached and a list of dependencies. The hook will return the cached value and only recompute the value if any of the dependencies have changed.
Here is an example of using the useMemo
hook in a React component that calculates the factorial of a number. The component has an input field that allows users to change the number. To prevent the component from re-calculating the factorial unnecessarily, we use the useMemo hook to memoize the calculation.
import React, { useState, useCallback } from "react";
const Factorial = () => {
const [num, setNum] = useState(0);
const factorial = useMemo(() => {
let result = 1;
for (let i = 1; i <= num; i++) {
result *= i;
}
return result;
}, [num]);
return (
<div>
<input
type="number"
value={num}
onChange={(e) => setNum(e.target.valueAsNumber)}
/>
<p>
Factorial of {num}: {factorial}
</p>
</div>
);
};
In this example, the calculation of the factorial will only be re-computed when the num state changes, for example: if you input 5 it will calculate the factorial of 5, and if you input 5 again it won’t recalculate and won’t cause a re-render because the value for 5 is already cached and the calculation will not re-run when other parts of the component change, making the component more efficient.
Difference between useMemo and useCallback
useMemo
and useCallback
are two React hooks that are used to optimize the performance of a React application. While they are similar in purpose, they have some important differences:
- Purpose:
useMemo
is used to memoize a value that is expensive to compute and is useful for optimizing performance when a component has expensive calculations or operations that can be reused, whileuseCallback
is used to memoize a function and is useful for optimizing performance when a callback is passed as a prop to a component. - Return value:
useMemo
returns a memoized value, whileuseCallback
returns a memoized function reference.
React.memo
React.memo is a HOC that wraps a React functional component and does an initial render of the component when it first loads and stores it in memory. When the props change React does a shallow comparison of prop values. If true
, React uses the memoized component and skips a re-render. If false
, React re-renders the component.
import React from 'react';
const MyComponent = React.memo(({ name }) => {
return (
<div>{name}</div>
);
});
export default MyComponent;
In this example, MyComponent
is a functional component that simply renders the name
passed to it as props. By wrapping MyComponent
in React.memo
, we are telling React to memoize the render of the component and only re-render it if its props have changed. This can greatly improve the performance of an application by avoiding unnecessary re-renders.
It’s important to note that React.memo
only shallowly compares the props of a component to determine if it should re-render. If you need to perform a deep comparison of props, you can pass a custom comparison function as the second argument to React.memo
. For functions passed as props, the useCallback
hook is handy for ensuring the same instance of the function is passed in as props.
import React, { useCallback } from "react";
const deepComparison = (prevProps, newProps) => {
//compare properties of objects of the prev and new
};
const MyComponent = React.memo(({ name, handleNameClick }) => {
return <div>{name}</div>;
}, deepComparison);
const MyOtherComponent = () => {
const handleNameClick = useCallback(() => {
//some actions here
}, [ depenencies here ]);
return (
<div>
<MyComponent handleNameClick={handleNameClick} />
</div>
);
};
In conclusion, React offers powerful memoization tools for optimizing the performance of React applications by avoiding unnecessary re-renders. It can help reduce the amount of work that a component has to do and make an application faster and more efficient.
When using React memoization, it’s important to keep the following notes in mind:
- Choose the right tool for the right case.
- Consider dependencies: When using
useMemo or useCallback
, be sure to pass in the correct dependencies to the hook so that the memoized value is only re-calculated when it is necessary, and pay attention to the comparison of props in case of using React.memo because in some cases you will need to make a deep comparison. - Avoid over-optimization: While React memoization can greatly improve the performance of a React application, it’s important not to over-optimize and make your code unnecessarily complex. Only use React memoization where it is needed and keep it simple and easy to understand.
- Test performance: Always test the performance of your React application after using React memoization to ensure that it has had the desired effect.
Overall, React memoization tools are valuable for optimizing the performance of a React application, and by using them correctly, you can make your application faster and more efficient.
Cheers 🥂 I hope you enjoy the article and learn something new.
Give claps 👏🏾 if you like it, and follow for more content like this. 🚀
Subscribe to my youtube channel where I make videos about Reactjs: https://www.youtube.com/channel/UCaloy_kzTcB415ogILETTrA and make a part of React Code Channel community to learn and be inspired learnhttps://chat.whatsapp.com/LJIdnfdMAlM7TZtNvKimS7