Skip to content

Instantly share code, notes, and snippets.

@bnguyensn
Last active January 1, 2022 17:58
Show Gist options
  • Save bnguyensn/38dfa3de6e9fc62069987b04fe656004 to your computer and use it in GitHub Desktop.
Save bnguyensn/38dfa3de6e9fc62069987b04fe656004 to your computer and use it in GitHub Desktop.
useCallback vs useMemo

useCallback vs useMemo

At a glance

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

useCallback useMemo
Function signature const someCallback = useCallback(() => { expensivelyCompute(a) }, [a]); const someValue = useMemo(() => expensivelyCompute(a), [a]);
What it does someCallback will only change if a changes. An example usage is when someCallback is passed down as a prop. The child receiving someCallback will only re-render when a changes. someValue will only be re-computed if a changes. Essentially the same someValue will never be calculated twice in a row (assuming expensivelyCompute() is a pure function, of course).
What it returns A memoized callback A memoized value
When to use Avoiding useless renders Expensive data processing
What if deps === undefined? someCallback will be updated on every render. someValue will be re-computed on every render.
Watch out for N/A The function () => expensivelyCompute(a) runs during rendering. Don't do any side effects in there (they belong in useEffect).

When to use?

Reference: Kent C. Dodds

Referential equality

Object-like things are never strictly equal to each other.

{} === {} // false
[] === [] // false

// etc.

Therefore, when you put object-like things in a React dependency array, the re-render will always happen.

useMemo and useCallback fixes this:

function ComponentA() {
  const memoizedFn = useCallback(() => {}, []);
  const memoizedArr = useMemo(() => [], []);
  
  useEffect(() => {
    doStuff(memoizedFn, memoizedArr);
  }, [memoizedFn, memoizedArr]);
  
  // ...
}

Computationally expensive calculations

useMemo helps when an expensive value is being calculated every render:

function ComponentA({ input }) {
  const memoizedValue = useMemo(() => expensivelyCalculate(input), [input]);
  
  // ...
}

What about React.memo?

const MyButton = ({ handleClick }) => (
  <button onClick={handleClick} />
);

// MyButton now uses shallow comparison.
// Any updates to the 'handleClick' function will be reflected inside <button>
export default React.memo(MyButton);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment