From React Class component to Functional component with hooks

Optimize React.memo with useCallback and useMemo

In the previous article, we discovered how to optimize React children components re-renders using React.memo (or memo). But the matter is that if the props received by the children components are objects, arrays or functions, the component will still re-render even if it has been memoized. To avoid these unwanted re-renders, these objects, arrays or functions props must be memoized in the parent component. Fortunately, React provides two hooks to do that: useCallback and useMemo.

Summary

The useCallback and useMemo Hooks are similar. The main difference is that useMemo returns a memoized value and useCallback returns a memoized function.

Cache functions with useCallback

What does useCallback do?

The React useCallback Hook returns a memoized callback function. That means that the value of the function is cached and does not need to be recalculated.

During the initial render the function is returned (not called).

On the next renders, the same cached function will be returned again if the dependencies have not changed since the last render. Otherwise, that is the function passed during the current render that is given and stored in case of later need.

The function is not called by React but returned so we can decide when and whether to call it. That way, we can improve performance by avoiding resource intensive functions to automatically run on every render.

When to use the React useCallback hook?

There are three situations when we can use the useCallback hook; when we want to:

  • skip re-rendering of children components by caching the function passed to child component which has been memoized with React.memo (or memo since React 18.2);
  • prevent an effect to be fired too often;
  • optimize a custom hook.

When not to use the React useCallback hook?

Do not use useCallback if:

  • the component is a class component,
  • the situation is not one of the ones cited above.

What is the useCallback struture?

The useCallback and useMemo structures are similar:

const cachedFuntionName = useCallback(function, dependencies);

or

const cachedFuntionName = useCallback(() => { // do something (a, b); }, [a, b]);

The function we want to cache can take any argument and return any value.  Each dependency (props, state, variables or functions declared directly inside the component body) listed in a array will be compared to its previous value. The useCallback Hook only runs when one of its dependencies updates.

How to implement useCallback?

  1. Write the original function and pass it as props to a child component or call it from the useEffect hook.
  2. Check that everything run correctly.
  3. Import it at the top of the file: import { useCallback } from 'react';
  4. It must be at the top of the functional component because it is a hook.
  5. Create a constant and give it the memoized function name.
  6. Call useCallback.
  7. Inside the useCallback hook, call the original function (or move the original function code in) and declare the array of dependencies.
  8. If the callBack is used as props in a child component replace the function name by the memoized function name.

Cache function value, object, array with useMemo

What does useMemo do?

The React useMemo Hook returns a memoized value. That means that the result, the value is cached and does not need to be recalculated.

During the initial render the function is called.

On the next renders, the same cached value will be returned again if the dependencies have not changed since the last render. Otherwise, the function calculating the value will be called, the result returned and stored to be reused later.

That way, we can improve performance by avoiding an expensive calculations to automatically run on every render.

When to use the React useMemo hook?

There are three situations when you can use the useCallback hook; when you want to:

  • skip expensive recalculations;
  • skip component re-rendering.

When not to use the React useMemo hook?

Do not use useCallback if:

  • the component is a class component,
  • the situation is not one of the ones cited above

What is the useMemo structure?

The useMemo and useCallback structures are similar:
const memoizedValue = useMemo(calculateValue, dependencies);

or

const memoizedValue = useMemo(() => functionName (a, b), [a, b]);

The function calculating the value we want to cache should be pure, take no arguments, and return a value of any type.Each dependency (props, state, variables or functions declared directly inside the component body) listed in a array will be compared to its previous value. The useMemo hook only runs when one of its dependencies updates.

How to implement useMemo?

  1. Write the original calculation function .
  2. Check that everything run correctly.
  3. Import it at the top of the file: import { useMemo } from 'react';
  4. It must be at the top of the functional component because it is a hook.
  5. Create a constant and give it the memoized function name.
  6. Call useMemo.
  7. Inside the useMemo hook, call the original function and declare the array of dependencies.

In conclusion

In this article, we have learnt how to optimize React re-renders using useCallback and useMemo to memoize props received by the React.memo memoized children components.

In a next article we will discover how to improve the performance, to optimize re-renders with the hook useRef.

Haut de page