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`
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 === sum2
evaluates 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!');
};
// ...
}
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:
- A functional component wrapped inside
React.memo()
accepts a function object prop - When the function object is a dependency to other hooks, e.g.
useEffect(..., [callback])
- 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!');
}, []);
// ...
}
handleClick
variable has always the same callback function object between renderings of MyComponent
.
Top comments (1)
Meaning, if I use callback hook for the functionA, and no mater how many time the react rerender the functionA still the only one?