Using useMemo instead of React.memo syntax issue
React.memo
and React.useMemo
are not equivalent at all (don't rely on naming similarity). Here's a quote from React.memo
doc:
React.memo
is a higher order component.
So it's a HOC that can optimize rendition of your component given that it renders the same output with the same properties.
React.useMemo
on the other hand is more generic and returns a memoized value:
Pass a “create” function and an array of dependencies.
useMemo
will only recompute the memoized value when one of the dependencies (eithera
orb
) has changed.
const memoizedValue = useMemo(
() => computeExpensiveValue(a, b),
[a, b]
);
And while it can be hacked to be used instead of React.memo
, it's not its purpose and it will add to the confusion more than it will help. useMemo
is a hook and is subject to the certain usage rules.
And there's this warning as well:
In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without
useMemo
— and then add it to optimize performance.
While memo
is a HOC and useMemo
is a hook, you can use them the achieve the same result.
For context, HOC is an older React pattern that has been used for many years with class-based and functional components alike. You can still use it today (there's no plan for deprecation).
Hooks is a relatively new concept (about a year) that enhances functional components and in many cases drastically simplifies code. That's why many developers are moving towards using hooks.
Anyway, both memo
and useMemo
take two arguments: a function and props. If none of the props change on subsequent re-renders, the function is not executed again and instead returns the previous result. This, in effect, replaces shouldComponentUpdate
callbacks, with a purely functional approach.
With memo
, your code would look like this:
const SpeakerCardDetail = React.memo(
(props) => <div>{props.name}</div>
)
With useMemo
, you'd write:
const SpeakerCardDetail = (props) => useMemo(() => <div>{props.name}</div>)
Notice that useMemo
is used inside of your component function, while memo
wraps the function.
More traditionally, useMemo
could be written as:
function SpeakerCardDetail(props) {
return useMemo(
() => <div>{props.name}</div>
)
}
Now, the code above would re-render every time, making the useMemo
function a bit useless. To make it work its magic, we need to add the second argument. (memo
still works even without specifying the second argument but you can add it to customize it)
There's a slight difference in the format of the second argument. memo
expects a function that compares previous and current props, just like shouldComponentUpdate
does for class components.
const SpeakerCardDetail = React.memo(
(props) => <div>{props.name}</div>
,
// return true if passing nextProps to render would return the same result as passing prevProps to render, otherwise return false
(prevProps, nextProps) => prevProps.name === nextProps.name
)
useMemo
, on the other hand, expects an array as the second argument. Whenever the values in the array change, the function would be executed again.
function SpeakerCardDetail(props) {
return useMemo(
() => <div>{props.name}</div>
,
[props.name]
)
}
There's really no more magic than that. Both memo
and useMemo
are used to memoize the result of a function, the only difference is memo
is a HOC (and can be used to wrap both class and functional components) which useMemo
is a hook (and can only be used inside functional components).