In this article we will explore the differences between React useMemo
and useCallback
hooks
If you are looking for a React Native Chat SDK to build in app chat messaging application, you can consider DeadSimpleChat React Native SDK
Core Difference
useMemo
: Returns a memorized valueuseCallback
: Returns a memorized function
Let us delve deeper into this
useMemo
useMemo is a React hook that lets you cache the result of a calculation that is value of a calculation between re-renders
If you are calculation something that is resource intensive, then you can cache the result of the calculation
And as long as the input of the calculations do not change you don't have to do the calculation again
Contrast this with
useCallback
useCallback
is a react hook that lets you cache a function definition between re-renders.
unlike useMemo, useCallback does not call the function that you provided. Instead it caches the function itself
you can think of useCallback
as a wrapper around useMemo with the additional benefits
This article is brought to you by DeadSimpleChat Chat API and SDK for your website and apps
Now, what does that mean? and How is that useful?
Let us consider an example to better understand this
Exploring the Differences
You can think of a website sellings products online. With one product on a single page and a buy button on the submit form
We have a Form
component from which users can order products, and we have wrapped it in a memo
Now, you want to pass a function to it as a prop
let us look at the code
The problem here is that, every re-render would create a new instance of the function.
Just as {}
creates a different Object, the function declarations like function () {}
or () =>{}
creates a new instance of the function
Now, the handleSubmit function is declared inside the ProductPage component.
So, everytime ProductPage
renders a new instance of handleSubmit will be created
By itself creation of a new function is not a problem but the whole point of memorizing
or caching the function is skipping the re-rendering of the component when no props have changed
However, if a function is passed as a prop to a memorized component is always different due to being re-declared on every re-render. It defeats the purpose of memorization
In this case the memorized function would re-render every time, since is function instance is different every time
To memorize a function with useMemo
, you will have to return another function like so
export default function Page({ productId, referrer }) {
//Memorizing the function
const handleSubmit = useMemo(() => {
//returning another function
return (orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
};
}, [productId, referrer]);
return <Form onSubmit={handleSubmit} />;
}
Here useCallback
comes to our help. you can wrap the function in useCallback
instead of useMemo
to avoid having to write an extra nested function
export default function Page({ productId, referrer }) {
const handleSubmit = useCallback((orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
}, [productId, referrer]);
return <Form onSubmit={handleSubmit} />;
}
The above two examples are the same. The only benefit of useCallback is that it lets you avoid that nest function
Understanding Memorization
Before understanding useMemo
and useCallback
it is essential to understand the concept of memorization
Memorization means caching the result of an expensive calculation, so that we do not run the calculation again unless the inputs have changed
This techniques are used to significantly improve performance where expensive computations are performed
How useMemo is used
the useMemo hooks is referenced as
useMemo(valueCalculation, dependencies);
valueCalculation is a function that returns a value that is to be memorized or cached and dependencies is an array of values from the components contexts.
If any value in the dependencies array changes then the valueCalculation function is re-invoked
Examples and Use-Cases of useMemo
Caching and skipping expensive calculation
One of the major advantages of useMemo is caching of expensive calculations to avoid calculating them on every re-render
And only run the expensive calculation when a input or prop changes, thus optimizing performance
Here the timeConsumingCalculation
will only happen if the hugeDataset changes
Skipping Re-rendering of Components
Child components can re-render if something in the parent (state changes) changes, if props are being passed down to the child
const someInformation = useMemo(() => {
return timeConsumingCalculation(data);
}, [data]);
<ChildComponent data={someInformation} />
Memorizing dependency of another hook
Many times a hook may have a dependency that has been derived from a state or a prop
You can memorize this dependency instead of recalculating the dependency on every render
const coolData = useMemo(() => processData(data), [data]);
useEffect(() => {
fetchData(coolData);
}, [coolData]);
Memorizing a function
You can memorize a function with useMemo
but you don't need to do that cause the useCallback
hook is available for that
Troubleshooting with useMemo
the calculation is running 2 with every re render
This happens during development mode for certain side-effects.
useMemo should return an Object but is returning undefined
ensure that your function is returning the correct value
Calculation rerun even if encapsulated in useMemo
The dependencies are changing at every re-render. ensure that the props or dependencies are not changing or you might need to use useCallback instead
Need to call useMemo for each item in a loop but it's not allowed
You might need to restructure you component, each item can be a component with its own useMemo
Examples and use-cases of useCallback
here is the reference
Skipping re-rendering of components
If a component is wrapped in a useMemo then passing a callback function to it will cause it to re render as function declaration create new functions
You can prevent the component to rerender because of the callbackfunction by using useCallback instead of useMemo
const handleSubmit = useCallback((someFunction) => {
}, []);
Updating state from a memorized callback
When you are dealing with updates in the memorized callback, it may lead to unexpected behaviour if the callback references to the state which is not updated
Preventing the effect from firing too often
In combination with useEffect
the useCallback
can prevent the effect from firing too often. If the dependencies have not changed
Optimizing a custom hook
Inside custom hooks the useCallback can be used to memorize dependencies to improve performance
You might be interested in some of our other articles
- useCallback: Guide, use-cases, examples
- React Hooks: Cheat Sheet, with examples
- React useDeferredValue
- useLayoutEffect vs useEffect with examples
conclusion
In this article we learnt about useMemo and useCallback. What are the differences between them and how do they work
Basically, useCallback is a wrapper around useMemo with additional benefit of caching hte function itself rather than the value returned by the function
This helps when you are passing a callback function as a prop to the component and you want to memorize it
This is because the funtion declaration such as function() {}
or ()=>{}
creates a new function and if oyu wrapped this component in useMemo
instead of useCallback
your component woild re render every time regardless of other props changing or not because new function is being created every time
To avoid this cache the function declaration itself instead of the returned value by using useCallback
I hope you liked the article. Thank you for reading