DEV Community

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

⚡️React Performance Optimization: useMemo vs useCallback

Ahmed Murtaza on January 08, 2023

useCallback and useMemo are both React Hooks that help optimize the performance of a React application by memoizing values. They both accept a func...
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
 
gomigoku profile image
Gouthami

Awesome explanation! Thank you!

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 :)