3

As I checked the React setState

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.

And this State Updates May Be Asynchronous

React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

What is the underlying mechanism? As I understand it, isn't it a batch update but queued following the First In First Out rule?

I am trying to make sure this FIFO rule for setState as follows:

this.setState({loading: true});
...// no matter what happened here as long as it's not stopped by errors;
this.setState({loading: false}); // the loading will always be set to **false**;

So I do not need to handle this as the following ugly way:

this.setState({loading: true}, () => {
    ...
    this.setState({loading: false});
});

Finally as I checked this Functional setState is the future of React, I think it indeed follows the FIFO rule.

To be super clear, passing object to setState() is not the problem here. The real problem is passing object to setState() when you want to calculate the next state from the previous state.

Hahah, Once and For ALL

Quote from Dan Abramov

It is safe to call setState with a function multiple times. Updates will be queued and later executed in the order they were called.

Please correct me if I'm wrong about this. And please share more details if it's available.

Thank you!

Hearen
  • 7,420
  • 4
  • 53
  • 63
  • Set the initial `state` in the constructor instead: `this.state = { loading: true };` –  Apr 17 '18 at 10:36
  • Can you make this happen in a [mcve], ideally a **runnable** one using Stack Snippets? (The `[<>]` toolbar button. Stack Snippets support React, including JSX; [here's how to do one](http://meta.stackoverflow.com/questions/338537/).) – T.J. Crowder Apr 17 '18 at 10:38
  • We can't help you with the code shown, we need more information (what's `askForData`? what does `dispatch` do?) Really, ideally, an MCVE. – T.J. Crowder Apr 17 '18 at 10:42
  • @T.J Sorry for the late reply, just updated the `askForData` – Hearen Apr 17 '18 at 10:58
  • 2
    That's great (and a significant change; important to ensure the question accurately reflects your real code **before** posting it), but it doesn't answer the questions above, and doesn't provide an MCVE. – T.J. Crowder Apr 17 '18 at 11:00
  • `setState` updates are queued (i.e. FIFO), so those two fragments should behave the same, unless `loading` is changed elsewhere. You could try logging all `setState` calls involving `loading` like this: `this.setState(() => {console.log('setState x'); return { loading: .. }});` and maybe check for promise rejections. – Oblosys Apr 17 '18 at 12:21
  • @Oblosys Thanks for the reply. I tried that and I got the sequenced log. But I want to make sure it's the case as you said `FIFO`. Is there some detailed doc or code I can check with this issue? @T.J.Crowder Please help!! – Hearen Apr 18 '18 at 00:40

3 Answers3

0

You don't seem to dispatch the action correctly, also the promise needs to handled with dispatch and not the function like

  dispatch(askForData()).then(() => {
    ...
    this.setState({ loading: false });
  };
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 3
    This makes at least two separate assumptions about the code that the OP's question doesn't justify. If `askForData` were a *function*, `askForData.then(...)` would throw an error. So it doesn't make sense to assume that `askForData` is a function, as the OP doesn't mention any error, but does mention the code shown updating `loading`. (The other assumption is that `dispatch` returns a promise rather than accepting a callback, but again, the OP's code shows it accepting a callback.) – T.J. Crowder Apr 17 '18 at 10:39
0

Yes, you can setState multiple times in a row, and the last call will determine the value of your state (if you set the same key, of course).

To be exact, the order of the updates may not exactly be the same as the setState calls, a matter of priority. Some calls can be skipped, and then replayed after the CPU has more time to offer. (much like a git rebase).

You can read more about this in this file, from the react source code.

Because React can batch updates (and ignore older value if they are overwritten), a case exists where you might need to call setState in another setState callback, it is if you NEED the state to have a specific value temporarily.

You may imagine a className depending on the state, that needs to be added and then quickly removed from the DOM to perform an animation.

Bear-Foot
  • 744
  • 4
  • 12
0

Have a look at THIS post by Dan Abramov to answer exactly this.

As per my understanding from the above post, you can assume that there is a single queue (FIFO) for the whole react project to which all updates are enqueued and later executed. Now you can see that order of setState is respected in a single component and even between different components.

You can also give THIS post a read, but here the author says

It turns out, every hook has an update queue.

whereas Dan Abramov's answer says that order of setState is respected even between different components, which I believe is only possible through a single queue like structure and NOT by multiple queues i.e. a queue for each useState hook.

I wish I could have tagged @Dan Abramov here to request his verification.

Aman Godara
  • 384
  • 1
  • 4
  • 6
  • I have found [**THIS**](https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/) (by [Mark Erikson](https://stackoverflow.com/users/62937/markerikson)) article which explain everything about React in super great details. – Aman Godara Nov 27 '21 at 18:02