Sobes.tech
Middle+

How do useMemo, useCallback, and React.memo work together? Why is it important to wrap functions in useCallback when passing to a child component wrapped in React.memo?

sobes.tech AI

Answer from AI

useMemo, useCallback, and React.memo work together to optimize React component performance by preventing unnecessary re-renders and re-creation of functions or values.

  • React.memo is a Higher-Order Component (HOC) that memoizes a component, preventing it from re-rendering if its props haven't changed compared to the previous render.
  • useCallback memoizes a function, returning the same function instance between renders if dependencies haven't changed.
  • useMemo memoizes a computed value to avoid recalculating it unnecessarily.

Why is it important to wrap functions in useCallback when passing them to a child component with React.memo:

If the parent component passes a function as a prop, that function is recreated on every render (a new object in memory). Even if other props haven't changed, React.memo will see that the function has changed (by reference) and will re-render the child component.

Wrapping the function in useCallback ensures that the reference to the function remains the same until dependencies change, allowing React.memo to effectively prevent unnecessary re-renders.

Example:

const Child = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click me</button>;
});

function Parent() {
  const [count, setCount] = React.useState(0);

  // Without useCallback, the function is recreated on every render
  // const handleClick = () => setCount(c => c + 1);

  // With useCallback, the function is memoized
  const handleClick = React.useCallback(() => setCount(c => c + 1), []);

  return <Child onClick={handleClick} />;
}

Without useCallback, Child will re-render on every Parent update; with useCallback, only when dependencies change.