DEV Community

Cover image for React.useCallback()
A.S.M. Habibullah Sadique
A.S.M. Habibullah Sadique

Posted on

React.useCallback()

Before diving into useCallback() usage, let's distinguish the problem useCallback() solves — the functions equality check.

Functions in JavaScript are first-class citizens, meaning that a function is a regular object. The function object can be returned by other functions, be compared, etc.: anything you can do with an object.

Let's write a function factory() that returns functions that sum numbers:

function factory() {
  return (a, b) => a + b;
}
const sum1 = factory();
const sum2 = factory();
sum1(1, 2); // => 3
sum2(1, 2); // => 3
sum1 === sum2; // => false
sum1 === sum1; // => true`
Enter fullscreen mode Exit fullscreen mode

sum1 and sum2 are functions that sum two numbers. They've been created by the factory() function.

The functions sum1 and sum2 share the same code source but they are different function objects. Comparing them sum1 === sum2evaluates to false.

The purpose of useCallback()

Different function objects sharing the same code are often created inside React components:

function MyComponent() {
  // handleClick is re-created on each render
  const handleClick = () => {
    console.log('Clicked!');
  };
  // ...
}
Enter fullscreen mode Exit fullscreen mode

handleClick is a different function object on every rendering of MyComponent.

Because inline functions are cheap, the re-creation of functions on each rendering is not a problem. A few inline functions per component are acceptable.

But in some cases you need to maintain a single function instance between renderings:

  1. A functional component wrapped inside React.memo() accepts a function object prop
  2. When the function object is a dependency to other hooks, e.g. useEffect(..., [callback])
  3. When the function has some internal state, e.g. when the function is debounced or throttled.

That's when useCallback(callbackFun, deps) is helpful: given the same dependency values deps, the hook returns the same function instance between renderings (aka memoization):

import { useCallback } from 'react';
function MyComponent() {
  // handleClick is the same function object
  const handleClick = useCallback(() => {
    console.log('Clicked!');
  }, []);
  // ...
}
Enter fullscreen mode Exit fullscreen mode

handleClick variable has always the same callback function object between renderings of MyComponent.

Top comments (0)