Rollie
Rollie

Reputation: 4752

Why do multiple setState calls in an async function cause multiple renders?

The issue is summarized well here; basically, if you have an async function in useEffect (which is where you'd expect such functions), you cause a re-render of your component for every state that is updated. I generally don't want to be bunching up things as in the authors solution/workaround, and to me this behavior doesn't make sense (you'd expect all your state updates to happen together).

Is this by design? If so, is there a better way to deal with this, such that I can perform all my updates without having to worry about ordering, etc? This feels like a bug, but maybe just a flaw in my understanding.

Code for reference:

export default function App (): JSX.Element {
  const [user, setUser] = useState(null)
  const [pending, setPending] = useState(false)
  
  useEffect(() => {
    setPending(true)
    fetchUser().then((fetchedUser) => {
      setPending(false)
      setUser(fetchedUser) // This updated value won't initially be seen by other effects dependant on 'pending'
    })
  }, [])
  // …
}

Upvotes: 2

Views: 625

Answers (1)

Rollie
Rollie

Reputation: 4752

Ended up figuring this out; see this. You need to manually batch things currently, with ReactDOM.unstable_batchedUpdates(() => { ... }). Despite the name, it is seemingly widely regarded as quite stable.

It is also corrected in the currently in-development Concurrent Mode for React.

Upvotes: 2

Related Questions