Reputation: 15478
In the react hooks doc, they give an example of using the useCallback React hook as follows:
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
I have an example that has a callback that gets called with a parameter (not a or b) and it seems to work. Please explain to me what a,b are and how they are meant to be used. Below is my working code using a callback.
const signupCallback = email => {
return console.log(`sign up called with email ${email}`);
};
const memoizedsignupCallback = useCallback(() => {
signupCallback();
}, []);
and the call that uses the callback.
<SignMeUp signupCallback={memoizedsignupCallback} />
Upvotes: 4
Views: 9286
Reputation: 333
You are correct in that useCallback
is used to memoize a function. You can think of a
and b
(or anything used in the second argument of useCallback
) as the keys to the memoized function. When either a
or b
change, a new function is created.
This is useful especially when you want something to be called on an onClick
that requires some values from your component's props.
Similar to your example instead of creating a new function on every render:
const Signup = ({ email, onSignup }) => {
return <button onClick={() => onSignup(email) } />;
}
you would use useCallback
:
const Signup = ({ email, onSignup }) => {
const onClick = useCallback(() => onSignup(email), [email, onSignup]);
return <button onClick={onClick} />;
}
This will ensure that a new function is created and passed to onClick
only if email
or onSignup
change.
Upvotes: 2
Reputation: 281666
The use of parameter a, b
depends on whether the function that you are trying to execute takes them from the enclosing scope or not.
When you create a function like
const signupCallback = email => {
return console.log(`sign up called with email ${email}`);
};
const memoizedsignupCallback = useCallback(() => {
signupCallback();
}, []);
In the above case memoizedsignupCallback
is created on initial render and it will have access to the values from the enclosing closure when it is created. Not if you want to access a value that lies within its closure but can update due to some interaction, you need to recreate the memoized callback and hence you would pass in the arguments to useCallback.
However in your case the value that memoizedsignupCallback
uses is passed on by the caller while executing the method and hence it would work correctly
Upvotes: 0
Reputation: 4436
This is the array of values that the hook depends on. When these values change, it causes the hook to re-execute. If you don't pass this parameter, the hook will evaluate every time the component renders. If you pass in []
, it will only evaluate on the initial render.
Documentation regarding this is available here: https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect.
If you do pass this array of parameters, it is very important to include all of the state that can change and is referenced in the hook closure. If you forget to include something, the values in the closure will become stale. There is an eslint rule that checks for this issue (the linked discussion also contains more details): https://github.com/facebook/react/issues/14920.
Upvotes: 2