React’s Memo, useMemo and useCallback


Uncategorized

Updated May 25th, 2023

Traditional/Classical definition of memoization stores a cache of result given certain arguments/props.

Note: Lodash has a memoize function for Traditional Memoization

const memoedCXFunction = _.memoize(CXFunction)

React.Memo

Memoization in React is a little different than standard memoization.

React.Memo is a higher order component, meaning it takes in a component.

Only when props changes, then re-render a component.

Wrap a component in Memo

const MemoedMyComp = React.memo(MyComp)

Should you use React.Memo? Re-Renders may not be so bad since if there are no changes between DOM/Virtual DOM nothing happens.

useMemo

React.memo works well with primitive values (booleans, numbers strings) for props but doesn’t work so well with objects or arrays for props.

When you pass an object as props React creates a new object with a new reference because React does a shallow comparison of props for valid performance reasons. Referential integrity at play. Comparison versus reference versus by value.

const params = useMemo(() => ({color}), [color])

Should I use useMemo? Depends.

Well this is Bad:

const value = useMemo(() => num1 + num2, [num1, num2])

So instead do:

const value = num1 + num2

Because the first value is a primitive value and so you’re not getting anything gained. Same goes for strings.

But a good case:

const value = useMemo(()=>numbers.reduce((a, v)=> a+v, 0), [numbers])

This is because numbers is an array

Another good case:

const multipliedValues = useMemo(()=>numbers.map(v=>v*100), [numbers])

Because we are returning an array.

And another good use case for objects:

const person = useMemo(()=>({first, last, full: `${first} ${last}`}), [first, last])

useCallback

In the example, Jack adds an empty “onClick” handler as props.

<MemoedSwatch onClick={()=>{}} />

This breaks React.memo due to a referential integrity issue.

Whereas useMemo deals with objects and arrays, useCallback deals with functions.

The useCallback hook gives you back the same function every time when you call it, (instead of creating a new function every time).

const onClick = useCallback(()=>{}, [])

And then pass this

Five Takeaways

React Memo is not a traditional memoization

Think of Memo as “render if props have changed.”

useMemo and useCallback are around inferential integrity

Use useMemo for expensive calculations

Don’t sweat component re-renders too much

Sources

Jack Herrington video here which this post is really just a transcription of.

Kyle at Web Dev Simplified has short videos with examples on useMemo, useCallback

Additional reading memo versus useMemo here