DEV Community

Cover image for ⚡️React Performance Optimization: useMemo vs useCallback
Ahmed Murtaza
Ahmed Murtaza

Posted on

⚡️React Performance Optimization: useMemo vs useCallback

useCallback and useMemo are both React Hooks that help optimize the performance of a React application by memoizing values. They both accept a function as an argument and return a memoized version of the function.

Here is a simplified explanation of the difference between the two:

useCallback

useCallback is a hook that returns a memoized callback. A callback is a function that is passed as an argument to another function. In the context of React, a callback is often used as an event handler or to pass data between components. The useCallback hook takes two arguments: a function and a dependency array. It will return a memoized version of the function that only changes if one of the dependencies has changed.

Here's an example of how you might use the useCallback hook:

Image description

In this example, the handleClick function is passed as an event handler to the button element. The useCallback hook ensures that the handleClick function is only re-created if the count prop changes. This can be useful if the ParentComponent is re-rendered frequently, as it can help to prevent the function from being unnecessarily re-created.

useMemo

useMemo is a hook that returns a memoized value. It takes two arguments: a function that returns a value and a dependency array. It will call the function and return its result only if one of the dependencies has changed.

Here's an example of how you might use the useMemo hook:

Image description

In this example, the processedData value is created by calling the function passed to useMemo. This function does some expensive processing with the data prop. The useMemo hook ensures that the processedData value is only re-computed if the data prop changes. This can be useful if the processing is time-consuming and you don't want it to be re-done unnecessarily.

Summary

To summarize, the main difference between useCallback and useMemo is the type of value they return. useCallback returns a memoized callback function, while useMemo returns a memoized value. Both hooks can be used to optimize the performance of your React components by avoiding unnecessary re-creations of functions or values.

Top comments (21)

Collapse
 
potcode profile image
Potpot • Edited

In your first example, handleClick will get recreated each time you click the button. You may change it to this:

const handleClick = useCallback(() => {
  setCount((old) => old + 1);
}, []); // dependency is also eliminated
Enter fullscreen mode Exit fullscreen mode
Collapse
 
raibtoffoletto profile image
Raí B. Toffoletto

Or Simply not use the hook. There's no reason to memoize this kind on function. 😉

Collapse
 
d4rkm3z profile image
Kirill Sadovnikov

Hook useCallback uses useMemo under the hood

Collapse
 
fullstackchris profile image
Chris Frewin

Do we have any benchmarks on how much more "optimized" this really is? I can't imagine how much performance is lost between:

const handleClick = useCallback(() => {
  setCount((old) => old + 1);
}, []);
Enter fullscreen mode Exit fullscreen mode

and

const handleClick = () => {
  setCount((old) => old + 1);
}
Enter fullscreen mode Exit fullscreen mode

If it isn't negligible, it has to be pretty close to it. I'd suppose any latency from things like fetching and so on make stuff like this pretty close to irrelevant. Would love to hear anyone's insights or reports from real app world.

Collapse
 
lwhiteley profile image
Layton Whiteley

I think it's not just the recreation of the function that you would need to take into consideration but the fact that not memoizing functions you pass to other components can cause them to also re-render unnecessarily. If that said component is heavy then it also degrades performance.

Just my two cents ;)

Collapse
 
fullstackchris profile image
Chris Frewin

But doesn't React already handle that anyway via props? If you're props to said component (or the component's own state) aren't changing, react isn't going to re-render anything

Thread Thread
 
diegobetto profile image
Diego Betto

But if the parent changes without child's props changing?
I think it can help in this case.

Thread Thread
 
lwhiteley profile image
Layton Whiteley • Edited

@fullstackchris There is a misconception there in what you think isnt changing.

React checks referential integrity to determine if a property has changed/not.

for each render the function's reference will be changed. Therefore, each time the parent re-renders it will pass a new function to the sub component and this component will think the function is new and changed since last render.

When you wrap the function in useCallback then it only changes the reference of the function when the dependencies change

Thread Thread
 
lwhiteley profile image
Layton Whiteley • Edited

PS:

This is essentially what React does to check equality by default

// falsy checks
Object.is({}, {}) // false
Object.is(() => {}, () => {}) // false

// same reference checks
const obj = {};
Object.is(obj, obj) // true

// primitives

Object.is(1, 1) // true

Enter fullscreen mode Exit fullscreen mode
Collapse
 
ahmedgmurtaza profile image
Ahmed Murtaza

Hi Chris. So the difference in performance between using useCallback and not using it in the example you provided is likely to be negligible. The primary benefit of useCallback is that it can help prevent unnecessary re-renders in certain situations by "memoizing" the callback function.

In your example, the callback function is only dependent on the setCount function, which is a constant value and will not change. In this case, useCallback is not necessary.

However, in more complex cases where the callback function depends on other state or props that may change, and the callback function is passed down as a prop to a child component, using useCallback can help prevent unnecessary re-renders and improve the performance of your application.

Collapse
 
diegobetto profile image
Diego Betto

This is a simple example just made for comprehension, consider this optimization in a more complex event handler for example.

Collapse
 
reacthunter0324 profile image
React Hunter

Great article!
It described the difference clearly, haha
Thank you

Collapse
 
ahmedgmurtaza profile image
Ahmed Murtaza

Thanks, glad you found this helpful! :)

Collapse
 
gilfewster profile image
Gil Fewster

Very clear explanation of the subtle difference between these two hooks. Nice one!

Collapse
 
ahmedgmurtaza profile image
Ahmed Murtaza

Thanks Gil :)

Collapse
 
edimeri profile image
Erkand Imeri

How did you get the processedData inside useMemo? Perhaps another example would have been better. Because you are returning the memoized function name declaration.

Collapse
 
mattbarnicle profile image
Matt Barnicle • Edited

The comment he wrote just above the return statement for processedData states that it's just a placeholder for some code where you would take the inputted data var, do some processing on it, save the results in processedData, and then return that var. It would have been more clear if he gave that var a different name though, for the name to be different than the memoized function name.

Collapse
 
ahmedgmurtaza profile image
Ahmed Murtaza

Exactly!

Collapse
 
dowscz profile image
Marek Schwarz

Just another GPT article... Horrible...

Collapse
 
rumendimov profile image
Rumen Dimov

Thanks for short and sweet explanation Ahmed, good content.

Collapse
 
ahmedgmurtaza profile image
Ahmed Murtaza

Thanks Rumen! Glad you found it useful :)