top | item 16230541

Why is setState asynchronous?

136 points| stablemap | 8 years ago |github.com | reply

45 comments

order
[+] ambrop7|8 years ago|reply
A (presumably controversial) way to use React is to use only props never state, manage state in your own variables (possibly in a separate "controller" class) and call forceUpdate() when you have changed those variables such that the render would change.

This gives me flexibility to structure the code how I want. You can have the separate "controller" classes deal with operations (like API requests) and the "react class" mostly deals with display - it delegates actions to the controller and retrieves data from the controller. This can promote code reuse, notably certain components can share the controller class (not instance) when you have similar logic.

As a more general principle, I like react just fine as a way to express the DOM in a functional way and for its magic of figuring out just what parts of the actual DOM must be updated; but I don't really care about how React wants me to write code in other aspects, like where and how I should manage my data.

[+] abritinthebay|8 years ago|reply
It's not controversial at all.

What is controversial is the (incorrect) notion that developers shouldn't use state. There are some perfect use cases for state and people somehow got the idea that they shouldn't use it (as opposed to not using it as the first tool, necessarily, if props can be used).

[+] acjohnson55|8 years ago|reply
This was exactly the motivation behind a project I wrote called react-redux-controller [1]. It has made for great separation of concerns between state management (Redux), display logic (React), and implementation of processes (the controller functions). It's completely possible to segment portions of the app such that slices of those three aspects are colocated and then composed as needed.

I don't necessarily recommend using this project specifically, as I don't devote any time to maintaining it. There's a whole next-generation of how I think it should work that I haven't gotten around to persuing. But I mention it to back the overall approach. It makes UI refactors extremely easy, as components are generally not responsible for any dependencies of their descendant subtree, with the exception of some parent-child interactions.

I haven't tried it, but I think Freactal [2] also seems to allow for this sort of separation of concerns.

[1] https://github.com/artsy/react-redux-controller

[2] https://github.com/FormidableLabs/freactal

[+] nawgszy|8 years ago|reply
You can also ignore React's built-in 'state' object and just store stuff directly in variables using MobX, which will force update components for you.

That said, it is best used as you describe it: a store that holds all the application state and manages API requests, and then any time it updates, any components observing this store will be forceUpdated

[+] sarreph|8 years ago|reply
I agree with your 'stateless' approach for many use cases that are otherwise 'muddied' by unnecessary component state.

However, instead of calling forceUpdate(), I was under the impression that componentWillReceiveProps(props) was more efficient?

Perhaps I'm wrong on that one, though... Just that forceUpdate() is an approach that is officially encouraged against.[0]

[0] - https://reactjs.org/docs/react-component.html#forceupdate

[+] sudhirj|8 years ago|reply
The question I ask when deciding between component state (via setState) or application state (via hoisting / redux / mobx) is simply whether the state is relevant to the application as a whole.

One example is the text I’m currently typing - that would only be relevant at a component level, maybe including an adjoining word counter. Once I hit reply, though, it becomes part of the application state.

An exception would be if I was continuously storing what was typed for offline use - in that case it’s always application state.

[+] qudat|8 years ago|reply
You are describing redux.
[+] josephorjoe|8 years ago|reply
They really should have just named it `queueStateChangeRequest` instead of `setState`, since it does the former and not the latter.
[+] rootlocus|8 years ago|reply
The title should probably mention the technology the question is referring to. This isn't a javascript forum...
[+] cryptonector|8 years ago|reply
The linked comment is very meaningful and comprehensible even if you're not a web developer (which I'm not). The only word in the title that may not be immediately meaningful is "setState", but the rest is still a huge draw for anyone who has had to deal with async code.
[+] globuous|8 years ago|reply
The url's actually pretty explicit ! (github.com/facebook/react).
[+] admax88q|8 years ago|reply
JS is a mess.

I think this blog post highlights the frustrating viral nature that is async functions:

http://journal.stuffwithstuff.com/2015/02/01/what-color-is-y...

[+] cryptonector|8 years ago|reply
JS is a mess, but async messes aren't JS's fault. Async is hard, but also everything just has to be async -- there's no way around this really. If you write sync code and later you need it to be async, then you're in for a full rewrite. If you write async code and you later need a sync version then you just add a wrapper that waits for completion.

In a world of fast CPUs, slow memory, distributed computing (whether client/server or peer-to-peer), remote function as a service, ..., asynchrony is a hard requirement.

The GUI event model has been with us since... even before the days of X11. Asynchrony in the UI is and long long has been a hard requirement. Users hate synchronous UIs, and rightly so.

Asynchrony is also difficult. But it's not like sync + threads is a panacea -- it's not because threads are way too heavy-duty. Better to deal with the pain than to deny the need.

[+] lucideer|8 years ago|reply
> JS is a mess.

The linked blog post doesn't seem to agree with you. He goes on to talk about Promises and async/await—both features of modern javascript—which he describes as "nice":

> Async-await is nice, which is why we’re adding it to Dart

He does finish by talking about Go's concurrency model, which he describes as being more "beautiful", but I still wouldn't confuse "it's nice" for "its a mess".

Also, the line about Java doing it better seems to be a joke.

[+] maxxxxx|8 years ago|reply
That's a good article. And yes, async is totally viral. Once you start using it, everything becomes async if you like it or not. I definitely need to study Go and goroutines. They seem to have a better approach.
[+] ocfx|8 years ago|reply
JS is a mess because React is using a concept similar to double buffering to prevent bad rendering? That's all this is, they are batching updates to the DOM before reconciliation to reduce redraws.