简体   繁体   中英

React useState hook, calling setState with function

There is a concept in React (when using hooks) that confuses me.

I made a component for explanation (that increases a counter):

const [counter, setCounter] = useState(0); // counter hook

// code will follow

// render
return (
  <div>
    <button onClick={handleClick}>+</button>
    <h3>{counter}</h3>
  </div>
);

For the handler function, I have seen different options to set the state.

First method (using setState() normally):

const handleClick = () => {
  setCounter(counter + 1);
};

Second method (creating a function inside setState() and returning the new value):

const handleClick = () => {
  setCounter((counter) => {
    return counter + 1;
  });
};

I thought the difference would be that with the second method, you could immediately do a callback after setting the state, like this:

const handleClick = () => {
  setCounter((counter) => {
      return counter + 1;
    }, () => {
      console.log(counter); // trying callback after state is set
  });
};

But when trying this (with both methods), the console displays the following error message:

Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().

So I think in both cases, using useEffect() as a callback on setState() is the right way.

My question is: what is the difference between the two methods and what method is best to set the state. I have read about state immutability but can not immediately see how it would make a difference in this example.

In your case it's the same.

Basically when your state is computed with your previous state you can use the second approach which gets the previous value.

Have a look in React docs about this:

Functional updates

Since this question is gaining some attention I will add this example.

<button onClick={() => setCount(0)}>Reset</button>
<button onClick={() => setCount((prevCount) => prevCount - 1)}>-</button>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>+</button>

You can see that for + and - the functional setState is being used, this is because the new state value is computed using the previous state (you are adding/subtracting from the previous count value).

The reset button is using the normal form, because it doesn't compute the new state value based on a computation on the old value, it always just sets it to a fixed number (for example 0 ).

So in my case, the best thing to do would have been using the functional setState .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM