Why Does My App Flash Blank Before It Loads, and How Do I Add a Loading State?
5 min read
Your app shows a blank white screen for a second before anything appears because it is waiting for data to arrive and has nothing to show in the meantime. The fix is a loading state: a spinner or a skeleton screen that fills the gap so the user knows content is on its way. It is a small change that makes the difference between "this feels broken" and "this feels fast."
Why this happens
When your page opens, it fetches data from somewhere, your database, an API, an AI endpoint, and that request takes time. On your laptop, on your fast connection, it takes so little time you barely see it. On a real user's phone on mobile data, it can take a full second or more. During that wait, the component has no data yet, so it renders nothing. That is the blank flash.
The reason your agent-built app does this is simple. You asked it to "show the user's dashboard," so it wrote the code that shows the dashboard once the data is there. You did not ask "and show something sensible while the data is still loading," so it did not. The happy path works perfectly. The one-second gap before the happy path just was never handled.
How to check
You need to see what your users see, not what you see on a warm, fast machine.
- Open your app in Chrome, press F12, and go to the Network tab.
- Find the throttling dropdown (it usually says "No throttling") and switch it to Slow 4G.
- Reload the page and watch closely. If you see a white or empty flash before content pops in, that is the problem your users hit.
- Repeat on any page that loads a list, a profile, a feed, or anything from a database. Each one can have its own flash.
The fix
- Find the loading flag. Most data-fetching code already tracks whether a
request is in progress. In React with a library like React Query or SWR, it
is
isLoading. With a plainfetch, you add aloadingstate that startstrueand flips tofalsewhen the data arrives. - Render something while loading is true. The quickest win is a centred
spinner:
if (isLoading) return <Spinner />. It tells the user the app is working, not frozen. - Prefer a skeleton screen for content pages. Instead of a spinner, show grey placeholder boxes shaped like the content that is coming: a grey bar where the title will be, grey lines where the text will be. The page stops jumping around when real data lands, which feels noticeably faster.
- Cover every fetch, not just the first page. Buttons that submit, filters that reload a list, "load more" actions, all of them have the same gap. Give each one a loading indicator, and disable the button while it works so nobody clicks twice.
- Re-test on Slow 4G. The flash should be replaced by a spinner or skeleton that appears instantly and is swapped for real content when it arrives.
The trap to avoid
Do not try to fix this by making the data load faster and calling it done. A
faster query still has a gap, and the gap still shows on a slow phone. Speed and
loading states are two different jobs: one shortens the wait, the other makes the
wait visible and calm. You want both, but the loading state is the part that
stops the app looking broken. Adding a fake setTimeout delay to "smooth" the
flash is the other trap, it just makes your fast users wait for no reason.
Where this fits
A blank flash is one of those things that never shows up in your own demo and always shows up for the friend you sent the link to. It sits right next to two cousins: what your app shows when there is genuinely no data yet and what it shows when a request fails. Getting all three right is a big part of feeling beta-ready. The free Readiness Report runs your app on a throttled connection and flags the pages that flash blank, and the Finishing Pass hands you the loading states to add, in order.