Race conditions in UI state
Slap yourself if
You think JavaScript being single-threaded means your UI state can’t race.
Why this exists
UI state races exist because modern frontends are event-driven, async by default, and optimistic about ordering. Promises, effects, network responses, and user input all resolve independently, while state is treated as if it were linear.
Mental model
UI state is a timeline, not a value. If you don’t control who’s allowed to write at each moment, the last resolver — not the correct one — wins.
- Multiple async operations capture different snapshots of state.
- Responses resolve out of order relative to user intent.
- State updates apply without validating freshness or relevance.
- The UI reflects a valid state transition — just not the intended one.
- Stale network responses overwriting newer user actions.
- Effects re-running with outdated closures.
- Optimistic updates not being reconciled correctly.
- Loading flags that lie about what’s actually in flight.
Race conditions in UI state occur when multiple asynchronous state updates resolve out of order, causing the UI to reflect stale or invalid transitions despite each update being logically correct in isolation.
- Boolean loading flags shared across requests
- State updates that don’t encode intent or versioning
- Assuming request order equals resolution order
- Ignoring cancellation or invalidation paths
Deep dive
Requires Pro
Premium deep dives include more internals, more scars.