Skip to content

RFClarification: why is setState asynchronous? #11527

Closed
@mweststrate

Description

@mweststrate

For quite a while I've tried to understood why setState is asynchronous. And failing to find an answer to it in the past, I came to the conclusion that it was for historical reasons and probably hard to change now. However @gaearon indicated there is a clear reason, so I am curious to find out :)

Anyway, here are the reasons I often hear, but I think they can't be everything as they are too easy to counter

Async setState is required for async rendering

Many initially think it is because of render efficiency. But I don't think that is the reason behind this behavior, because keeping setState sync with async rendering sounds trivial to me, something along the lines of:

Component.prototype.setState = (nextState) => {
  this.state = nextState
  if (!this.renderScheduled)
     setImmediate(this.forceUpdate)
}

In fact, for example mobx-react allows synchronous assignments to observables and still respect the async nature of rendering

Async setState is needed to know which state was rendered

The other argument I hear sometimes is that you want to reason about the state that was rendered, not the state that was requested. But I'm not sure this principle has much merit either. Conceptually it feels strange to me. Rendering is a side effect, state is about facts. Today, I am 32 years old, and next year I will turn 33, regardless whether the owning component manages to re-render this year or not :).

To draw a (probably not to good) parallel: If you wouldn't be able to read your last version of a self written word document until you printed it, that would be pretty awkward. I don't think for example game engines give you feedback on what state of the game was exactly rendered and which frames were dropped either.

An interesting observations: In 2 years mobx-react nobody ever asked me the question: How do I know my observables are rendered? This question just seems not relevant very often.

I did encounter a few cases where knowing which data was rendered was relevant. The case I remember was where I needed to know the pixel dimensions of some data for layout purposes. But that was elegantly solved by using didComponentUpdate and didn't really rely on setState being async either. These cases seem so rare that it hardly justify to design the api primarily around them. If it can be done somehow, it suffices I think


I have no doubt that the React team is aware of the confusion the async nature of setState often introduces, so I suspect there is another very good reason for the current semantics. Tell me more :)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions