MuffinColor
MuffinColor

Reputation: 21

I don't understand useCallback

I need to change the checkbox checked status, but useCallback re-renders component a lot of times. I don't understand how it works. I've read a lot of materials about it.

const AppealsList = () => {
  const [isFiltered, setFiltered] = React.useState(false);
  console.log('rerender');

  const changeCheckBox = useCallback(() => {
    setFiltered(!isFiltered);
  }, [isFiltered]);

  return (
    <div className={classNames('appeals')}>
      <div className={classNames('appeals__filter')}>
        <input
          checked={isFiltered}
          className={classNames('appeals__input')}
          type="checkbox"
          readOnly={true}
        />
        <label
          onClick={changeCheckBox}
          className={classNames('appeals__filter-label')} />
      </div>
    </div>
  );
};

Amount of re-renders:

Amount of re-renders

Upvotes: 1

Views: 1431

Answers (2)

Brandon
Brandon

Reputation: 39222

This is because you have written your callback with a dependency on isFiltered so it will change every time you click. It works best when it does not depend on the very state that the callback is changing.

To create a toggle function that does not constantly change, have it call setState with a function so that it can compute new state from previous state, taking advantage of functional state updates offered by useState:

const changeCheckbox = useCallback(() => {
    setFiltered(currentValue => !currentValue);
}, []); // look no dependencies!

You can read about functional state updates (deriving new state from current state) here: https://reactjs.org/docs/hooks-reference.html#functional-updates

If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value.

Upvotes: 1

Colin Hale
Colin Hale

Reputation: 870

setCallback is used to memoize functions so if you have heavy functions that require a lot of processing you don't have to processes the same inputs twice. For example if you had a function that adds two numbers and you give it 4 and 3 then it runs the function and memorizes that when you input 4 and 3 into the function the result is 7. So next time it is passed 4 and 3 instead of processing the result it uses the memorized result.

While useCallBack is used to memorize functions, useEffect is used to prevent unnecessary rerenders. I think in this case you are wanting to use the useEffect Hook?

Upvotes: 0

Related Questions