score:2

Accepted answer

In promise callback, you set the state only once on the first setState(_state);, on every other try, the component doesn't render because as React rendering works, it makes shallow comparison with the previous state, which is always true because it holds the same object reference (it's javascript):

const state = { a: 1};
setState(state); // prevState = state;

state.a = 2;
prevState === state // always true so not render is triggered

Its a common beginner mistake, React states to treat state as immutable..

score:2

The reason why React is not rendering the latest state is because you're directly manipulating state by doing the following:

const _state = { a: 1 };

setState(_state);

// you're using the same object
_state.a = 2;
setState(_state);

// you're using the same object here too
_state.a = 3;
setState(_state);

You should not be mutating state directly and you should treat state as it were immutable.

To fix this, you need to make a copy of your state, update whatever properties you want, and then use that new object to update your state.

const handleClick = () => {
  Promise.resolve().then(() => {
    const _state = { a: 1 };

    console.log("1");
    setState(_state);

    console.log("2");
    const _state2 = { ..._state, a: 2 };
    setState(_state2);

    console.log("3");
    const _state3 = { ..._state, a: 3 };
    setState(_state3);
    console.log("3");
  });
};

Here's a working example:


Also, React will batch state updates so sometimes if you're not seeing "correct behavior" when you call setState multiple times in a row for the same piece of state it's because React is trying to prevent unnecessary re-renders by batching those updates. In your case, however, they will not be batched since they are triggered in a Promise.

See here for more information on how batching works in regards to state updates:


Related Query

More Query from same tag