I've been learning React and ran into a problem that's tricky to Google. When my component mounts, I fire off a list of XHR calls to an external service. When each one returns, I want to update the state. Here was my first attempt:

class SomeComponent extends React.Component { componentDidMount() { const xhrCalls = ['http://www.example.com','...']; xhrCalls.forEach((url) => { $.ajax(url, (results) => { /* this.state.results is an immutable list; this.state.results.push yields a new list with the item added. */ let newState = this.state.results.push(result); this.setState(newState); }); }); } }

What ended up happening was weird and surprising: My state got updated a bunch of times: so far so good. But, the state only had the results of the last XHR request. I was losing all the state updates except the last.

After a lot of messing around, I figured out that setState is asynchronous. If you call this.setState , the value of this.state is not guaranteed to update right away. You can pass a callback as a second argument to setState that will be called once the state has been modified.

This led me down a weird path of thinking about concurrency primitives to assure atomic updates. This is even weirder because JavaScript is not a concurrent programming environment.

Finally, I figured out that setState has another form that takes a function. The function takes a state object and returns a modified version. This is guaranteed to happen atomically.