Stop 10 · API IntegrationTopics · 12/16

Loading State

Part of the Frontend Developer Roadmap

In short

Users can wait a second or two if they can see something is happening. A blank screen for the same time feels broken. Loading states fix that.

Tracking and displaying whether an API request is in flight, so users see spinners/skeletons instead of a blank or frozen UI.

The jaadu relaxes on a sofa watching an order tracker on a phone as a pizza box arrives.

Think of it like this

The live order tracker

Swiggy doesn't make you stare at a white page after you pay. It shows 'Order placed', 'Being prepared', 'Out for delivery'. The wait is the same, but you feel calm because you can see progress. That's a good loading state.

Watch it happen

One status value at work

loading
success
error
retry

1/6status starts as loading, so five skeleton cards fill the space.

The big ideas

What you need to know

Skeletons over spinners

Grey boxes in the shape of the real content feel faster and stop the layout jumping when data arrives.

Disable while submitting

Turn the button into 'Saving...' and disable it, so impatient double clicks don't send two orders.

Use one status value

A single status of 'idle', 'loading', 'success' or 'error' avoids impossible combos like loading and error at once.

Don't flash for tiny waits

For very quick loads, a spinner that blinks for 50 ms looks glitchy. Keep old content visible instead.

See it in code

Walk through the code

tsx
1type Status = "loading" | "error" | "success";2const [status, setStatus] = useState<Status>("loading");3const [posts, setPosts] = useState<Post[]>([]);4 5useEffect(() => {6  getPosts()7    .then((data) => { setPosts(data); setStatus("success"); })8    .catch(() => setStatus("error"));9}, []);10 11if (status === "loading") return <PostSkeleton count={5} />;12if (status === "error") return <ErrorBox onRetry={() => location.reload()} />;13return <PostList posts={posts} />;

1/3A single status with three allowed values, starting at loading.

One status variable, three clear screens. The skeleton matches the list's shape, so nothing jumps when the real posts appear.

Save yourself the pain

Common mistakes

Oops

Using separate isLoading and isError booleans and forgetting to reset one.

Do this instead

Use a single status value, so only one state can be true at a time.

Oops

Leaving the submit button clickable while the request is in flight.

Do this instead

Disable it and change its label until the response comes back.

Your mission

Make waiting feel good

~25 min

Quick check

Why are skeleton screens often better than a centred spinner?

Go deeper

  1. 1Add explicit loading, error and success states to a data-fetching component.
  2. 2Build a reusable skeleton loader component for cards/lists.
  3. 3Avoid flashing a loading spinner for extremely fast requests — add a small delay.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge