axtck
axtck

Reputation: 3965

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.

Upvotes: 4

Views: 6704

Answers (2)

axtck
axtck

Reputation: 3965

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 setStateis 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.

Upvotes: 0

zb22
zb22

Reputation: 3231

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

Upvotes: 1

Related Questions