The In-Between States

Have you ever used an app and thought "this feels slow" or "this is janky" without knowing exactly why? The answer often lies in the in-between moments—loading screens, error states, and the gaps between user action and final render.

The Coordination Problem

Building async UIs has always been difficult. Navigation hides content behind spinners, search boxes create race conditions, and form submissions require manual state management for every loading flag. Every async operation forces you to orchestrate the coordination manually.

This isn't a performance problem—it's a coordination problem. And React's primitives now solve it declaratively.

What Happens Between?

Every async operation has three phases:

User Action → Loading → Success or Error

In React applications, this happens constantly:

  • Async data loading — Fetching content from the server
  • Async mutations — Submitting forms, toggling states
  • Async routing — Navigating between pages

Why These Moments Matter

The in-between states determine how polished your app feels:

Bad UXGood UX
Blank screensSkeleton placeholders
Jumping layouts (CLS)Stable, reserved space
Frozen buttonsInstant optimistic feedback
Full-page spinnersLocalized loading indicators
Generic errorsContextual error recovery

Not a DX Problem

These are UX problems, which is why engineers often overlook them. We focus on making things work, not on what users see while they wait.

The following posts explore each pattern with real examples from this app—showing how to coordinate loading, mutations, and navigation seamlessly.

November 6, 2025Updated March 30, 2026263 words