UseCallback & UseMemo — A Side Note to the Official Doc
The following can be read as a side reference to the official React Doc:
UseCallback
Pass an inline callback and an array of dependencies. useCallback
will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate
).
useCallback(fn, deps)
is equivalent to useMemo(() => fn, deps)
.
UseMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Pass a “create” function and an array of dependencies. useMemo
will only recompute the memoized value when one of the dependencies has changed.
As you can see, useMemo
takes in a function and a list of dependencies (the array [a, b]
). The dependencies list are the elements useMemo watches: if there are no changes the function result will stay the same, otherwise it will re-run the function. If they don’t change, it doesn’t matter if our entire component re-renders, the function won’t re-run but instead return the stored result.
const List = useMemo(
() =>
listOfItems.map(item => ({
...item,
itemProp1: expensiveFunction(props.first),
itemProp2: anotherPriceyFunction(props.second)
})),
[listOfItems]
)
In the above example, the useMemo function would run on the first render. It would block the thread until the expensive functions complete, as useMemo
runs in the render. Initially, this won’t look as clean as useEffect, since useEffect can render a loading spinner until the expensive functions finish and the effects fire off. However, the expensive functions would never fire off again if listOfItems
never changed and we would still get the return value from them. It would make these expensive functions seem instantaneous. This is ideal of you have an expensive, synchronous function or two.
If no array is provided, a new value will be computed on every render.
You may rely on useMemo
as a performance optimization, not as a semantic guarantee.
So what’s the difference between useCallback and useMemo?
The signature of useCallback
and useMemo
look similar. They both take in a function and an array of dependencies.
useCallback(fn, deps);
useMemo(fn, deps);
But useCallback
returns the function uncalled so you can call it later, while useMemo
calls its function and returns the result.
In this case, useCallback(fn, deps) === useMemo(() => fn, deps)
.