All posts
June 3, 2026 · Snapdock

Why Does My App Feel Slow? How to Add Loading States.

You built an app with Claude, ChatGPT, Bolt, or Lovable and sometimes when users click a button or submit a form, nothing seems to happen for a few seconds…

You built an app with Claude, ChatGPT, Bolt, or Lovable and sometimes when users click a button or submit a form, nothing seems to happen for a few seconds. The button just sits there. The page looks frozen. Users click again, wondering if it worked. Sometimes they click three times and submit the form three times. This is a loading state problem, and it is one of the most impactful UX improvements you can make with minimal effort.


What a Loading State Is

A loading state is feedback your app gives users to communicate that it is working on something. A spinner. A button that changes to say “Saving…” A skeleton placeholder where content will appear. A progress bar.

A one-sentence definition: a loading state is a visual indicator that tells users your app is processing their request so they know it received the action and are not left wondering if anything happened.

Without loading states, users have no feedback loop. They click and wait in silence. They do not know if the app received their click, if something broke, or if they need to try again. This uncertainty leads to repeated clicks, frustration, and the impression that your app is broken even when it is working correctly.


The Four Most Common Loading Patterns

Button loading state. When a user clicks a button, the button changes to show it is working. The text might change from “Save” to “Saving…” and the button becomes disabled to prevent duplicate submissions.

Spinner overlay. A spinning icon appears while content is loading. Good for full-page loads or when the user needs to wait for a result before doing anything else.

Skeleton loading. Instead of a spinner, a grey placeholder in the shape of the content appears while the real content loads. Feels faster because the layout does not jump when content arrives. Used by LinkedIn, Facebook, and most modern apps.

Inline loading indicator. A small spinner or progress indicator next to a specific element that is loading, without blocking the rest of the page.


How to Add a Button Loading State

This is the most impactful and easiest to implement. Ask your AI:

“When a user clicks the [button name] button in my app, can you add a loading state? The button should change its text to [e.g. ‘Saving…’ or ‘Submitting…’], show a spinner, and be disabled to prevent double-clicks. When the action completes or fails, the button should return to its normal state.”

In React, this typically involves a useState hook for an isLoading boolean that controls the button’s appearance and disabled state. Your AI will handle the implementation.


How to Add Skeleton Loading

Skeleton loading is more involved but dramatically improves the perceived speed of your app. Instead of a blank page while data loads, users see a rough outline of the content that fills in with real data.

Ask your AI: “Can you add skeleton loading to my [page or component name]? While the data is fetching, show grey placeholder shapes in the layout of the content rather than a spinner or blank space.”

Most modern UI libraries including shadcn/ui and Tailwind have skeleton components built in. Your AI will use the appropriate one for your stack.


How to Prevent Double Submissions

Double submission, where a user clicks a button twice and the action happens twice, is one of the most common bugs in web apps and the most preventable.

The fix is always the same: disable the button immediately when clicked and re-enable it only when the action is complete. Ask your AI: “Can you make sure that clicking the submit button twice does not submit the form twice? Disable the button immediately on first click and only re-enable it after the response comes back.”


The One Thing to Remember

Loading states tell users your app received their action and is working on it. The most impactful improvement is adding loading states to buttons that trigger actions. Change the button text, add a spinner, disable it immediately. This prevents double submissions and eliminates the “did it work?” uncertainty that makes apps feel broken.


Want your app running fast and responsively in production? → Snapdock

New here? These might help: Why is my app slow? How to make it faster without a developer. → Why does my app forget everything when I refresh the page? →