So supposedly, useCallback can cache a function, and I think the intention is to make the code run faster.
So for example, if I have:
const handleChange = (ev) => {
setMsg(ev.target.value);
};
I also can change it to:
const handleChange = useCallback((ev) => {
setMsg(ev.target.value);
}, []);
so that now the function cached. However, doesn’t this function need to be created every time the component is re-rendered anyway?
To test it, I change it to an IIFE, so that the function is spit out from it, and it would print out the function is being spit out.
See:
https://codesandbox.io/s/jolly-nightingale-zxqp8k
So every time when you type something into the input field, a new function is spit out, as seen in the console. So that means, the IIFE is executed every time any way, and that means, even when it is not an IIFE, the function literal is made into a function object each time. So how does that help the code run faster at all?
2
Answers
Yes, that’s correct. A new function will be created on every render, and then the new one will be thrown out in favor of the cached one.
The speed up doesn’t come from skipping creating the function. Instead, it comes from other pieces of code being able to skip their work. And this happens because if they’re passed the same function every time they can know that nothing relevant has changed.
For example, if you need to pass
handleChange
into the dependency array of a useEffect, it’s important to pass a stable reference each time or the effect will be re-run on every render:Or if
handleChange
is being passed as a prop to a component, and that component wants to skip rendering withReact.memo
. The render can only be skipped if the props don’t change:The question has many answers. Because the answer changes it’s logic based on situation.
The gist of the answer is "You have to understand the need and use accordingly"
Suppose you have a function that you used as a props for other component. In this situation you can wrap the function in a
useCallback
. Sometime the component can be very simple but thedependency
array of theuseCallback
hook can be a large and nested object. In that case wrapping the function in auseCallback
hook might not be a good idea. Because the computationuseCallback
will do in every render doesn’t worth for the component to re-render.We have to keep in mind that React is designed to re-render the component. So when you ask React not to re-render that decision need to be a well thought decision.
I got to know about this concept very well from the blog that is written by the creator of React testing library Kent C. Dodds. I liked how he explained about both
useCallback
anduseMemo
. Here is the link – https://kentcdodds.com/blog/usememo-and-usecallback