Set useState hook in a async loop
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Using useState inside asynchronous loops is less about whether React allows it and more about how state updates are scheduled. The safe pattern is to either use functional updates for each asynchronous result or accumulate the results first and update state once, depending on whether intermediate renders are desirable.
The core problem is stale state, not the loop itself
React state setters do not update the state variable immediately. They schedule a re-render. In an async loop, that means code that reads the current state value can easily capture a stale snapshot.
Bad pattern:
The results variable here is the value from the render that created the loop, not the latest state after each update.
Use functional updates when appending incrementally
If you want the UI to update after each asynchronous step, pass a function to the setter. React then gives you the latest committed state.
This works because prev is always the latest state, even if several async completions happen across different renders.
Update once when you do not need intermediate renders
If the UI does not need to show partial progress, accumulate locally and set state once at the end. This is often simpler and causes fewer re-renders.
This is a good default when the only useful UI state is the final result.
Run async loops from effects or handlers, not during render
Do not start async work directly in the component body. Rendering must stay pure. Start the loop inside an event handler or inside useEffect.
The cancellation guard prevents state updates after unmount.
Consider parallel work when order does not require sequencing
Many async loops are sequential by habit, not by necessity. If the requests are independent, Promise.all is often faster and simpler.
That avoids repeated state writes and shortens total wait time.
Common Pitfalls
- Reading a stale state variable inside the async loop and appending from outdated data.
- Starting the async loop during render instead of in an effect or event handler.
- Updating state on every iteration when one final update would be simpler and cheaper.
- Forgetting cleanup logic and calling
setStateafter the component unmounts. - Using sequential awaits when the operations could safely run in parallel.
Summary
- '
useStateworks with async loops, but stale state is the main hazard.' - Use functional updates when each async completion should update the UI.
- Accumulate locally and call
setStateonce when partial progress is unnecessary. - Start async loops from effects or handlers, never from render.
- Use cleanup guards or cancellation when the component may unmount mid-request.
Related reading
- setTimeout in React Native
- Setting up a multi-threaded Pyro project
- Should a return statement be inside or outside a lock?
- Should a return statement be inside or outside a lock?
- sh 1 react-scripts not found In Docker
- sh husky command not found
- Should I add async/await to a single-line function or not?
- Should I always use a parallel stream when possible?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.