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.

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
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
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
Quick check
Why are skeleton screens often better than a centred spinner?
Go deeper
- 1Add explicit loading, error and success states to a data-fetching component.
- 2Build a reusable skeleton loader component for cards/lists.
- 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.