- useCallback() often is used in conjunction with useEffect() because it allows you to prevent the re-creation of a function.
const MyComponent = props => {
const innerFunction = () => {
// a function in a function!
// this function object (stored in the 'innerFunction' constant) is constantly re-built
// to be precise: It's re-built when MyComponent is re-built
// MyComponent is re-built whenever its 'props' or 'state' changes
};
};
- Typically, it’s not a problem, that innerFunction is re-created for every render cycle. But it becomes a problem if innerFunction is a dependency of useEffect():
const MyComponent = props => {
const innerFunction = () => {
// do something!
};
useEffect(() => {
innerFunction();
// The effect calls innerFunction, hence it should declare it as a dependency
// Otherwise, if something about innerFunction changes (e.g. the data it uses), the effect would run the outdated version of innerFunction
}, [innerFunction]);
};
- Because functions are objects and objects are reference types, that means that the effect will re-run for every render cycle.
That might still not be a huge problem, but it is, if innerFunction does something that causes MyComponent to re-build (i.e. if it either does something that changes the props or the state).Now, you would have an infinite loop!
useCallback() helps you to prevent this.
const MyComponent = props => {
const innerFunction = useCallback(() => {
// do something!
});
useEffect(() => {
innerFunction();
// The effect calls innerFunction, hence it should declare it as a dependency
// Otherwise, if something about innerFunction changes (e.g. the data it uses), the effect would run the outdated version of innerFunction
}, [innerFunction]);
};
- By wrapping it around a
useCallback() function declaration and defining the dependencies of the useCallback() function, it ensures that the function is only re-created if its dependencies changed.