Peter Kellner
Peter Kellner

Reputation: 15478

In React Hook useCallback, How are (a,b) used

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

Answers (3)

jhsu
jhsu

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

Shubham Khatri
Shubham Khatri

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

DEMO

Upvotes: 0

Joru
Joru

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

Related Questions