DEV Community

Cover image for `useCallback` vs `useMemo` Hooks

`useCallback` vs `useMemo` Hooks

Sivasubramaniyam on September 19, 2024

React Learning Guide Boosting React Performance: useCallback vs. useMemo Hooks React's useCallback and useMemo hooks are crucial for op...
Collapse
 
lwhiteley profile image
Layton Whiteley

Nice article.

One point of feedback. Examples in best practices articles can often be seen as good practices so ensure they are optimal as well.

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

This code has a hidden bug as the state can be stale if a user is clicking fast

A better way to write this is

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

Given that the example is trying to showcase the dependency array then maybe rework the example to use another dependency

Collapse
 
martinbaun profile image
Martin Baun

Great read! Looking forward to more like these!

Collapse
 
sivamani18 profile image
Sivasubramaniyam

I will be posting relevant topics to 'Mastering React' and adding appropriate links to each topic.

Collapse
 
elielson77 profile image
Elielson Melo

Thank you, I will try these tips

Collapse
 
ramk777stack profile image
Ramkumar.barani

Very informative, thanks for sharing.

Collapse
 
trisogene profile image
Daniel Dallimore Mallaby

This is not 100% correct, the child component will still rerender since his father state changed.

In order to prevent rerender of the child you will have to memoize the child ( export it with memo(ChildComponent)) so that this will only rerender if the props change.

Then as the article say you need to wrap function inside a usecallback so that when the father component rerender the function that will be passed as props wont change, thus the child component will not rerender.

Collapse
 
sivamani18 profile image
Sivasubramaniyam

Thank you for your feedback! 🙏

You're absolutely right. I should have included the step about memoizing the child component using React.memo to fully prevent it from re-rendering when the parent state changes.

This ensures that:

  • The ChildComponent only re-renders if its props change.
  • The useCallback hook prevents unnecessary re-creations of the handleIncrement function when the parent component re-renders.

Thanks again for pointing this out! 🙌

Collapse
 
lwhiteley profile image
Layton Whiteley • Edited

This rebuttal is not true.

If the props don't change then react will not rerender the child component even if the parent state changes.

Rerendering child components would be a massive performance hit for the tree if their props don't change

To prevent rerendering of child component you must first ensure it's props are stable meaning they only change when they need to.

If you need to further optimize when the component rerenders then you can use React.memo to exclude some props from consideration or change the default equality check that react uses which is Object.is

Object.is is a reference equality check

Adding React.memo on a component without first optimizing it's props will not have any effect

This can be easily tested by adding console logs in a component and changing the state in the parent and seeing if the child component renders a log. Or just use react dev tools.

This is all discussed on the react docs

react.dev/reference/react/memo

You should only rely on memo as a performance optimization. If your code doesn’t work without it, find the underlying problem and fix it first. Then you may add memo to improve performance.

Collapse
 
sivamani18 profile image
Sivasubramaniyam

The rebuttal you received is mostly correct when they argue that React won't re-render the child component if the props haven't changed. Indeed, React.memo should only be used after ensuring the props passed to the child are stable. However, useCallback plays a role in keeping the function reference stable—a common scenario that could otherwise lead to unwanted re-renders.

  • Stable props: Ensuring props are stable is the key point, and useCallback is one of the tools to achieve that for function props.
  • React.memo helps optimize the re-rendering process, but without stable props (like an unstable function reference), its benefits are limited.
Thread Thread
 
lwhiteley profile image
Layton Whiteley

However, useCallback plays a role in keeping the function reference stable

Yep that is my point

Collapse
 
wra-sol profile image
Nathaniel Arfin

useMemo and useCallback will be deprecated in React 19, FYI!

Collapse
 
sivamani18 profile image
Sivasubramaniyam

Thanks for the heads-up! 🙌

While it's good to stay informed about upcoming changes, a lot of companies are still running on older versions like React 16 or 17. In fact, some organizations take years before upgrading to the latest major versions due to stability concerns or the size of their codebase.

So, even though useMemo and useCallback might be deprecated in React 19, these hooks will likely still be widely used in production environments for quite a while. 😊

But it's always good to be aware of what's coming—thanks again for sharing! 🙏

Collapse
 
lwhiteley profile image
Layton Whiteley • Edited

I don't think they will be deprecated. The react compiler just automatically adds them for you.

That's not really a deprecation