Modern React UI patterns for loading states, error handling, and data fetching. Use when building UI components, handling async data, or managing UI states.
Add this skill
npx mdskills install sickn33/react-ui-patternsComprehensive React UI patterns with clear decision trees and anti-pattern examples
Show loading indicator ONLY when there's no data to display.
// CORRECT - Only show loading when no data exists
const { data, loading, error } = useGetItemsQuery();
if (error) return ;
if (loading && !data) return ;
if (!data?.items.length) return ;
return ;
// WRONG - Shows spinner even when we have cached data
if (loading) return ; // Flashes on refetch!
Is there an error?
→ Yes: Show error state with retry option
→ No: Continue
Is it loading AND we have no data?
→ Yes: Show loading indicator (spinner/skeleton)
→ No: Continue
Do we have data?
→ Yes, with items: Show the data
→ Yes, but empty: Show empty state
→ No: Show loading (fallback)
| Use Skeleton When | Use Spinner When |
|---|---|
| Known content shape | Unknown content shape |
| List/card layouts | Modal actions |
| Initial page load | Button submissions |
| Content placeholders | Inline operations |
1. Inline error (field-level) → Form validation errors
2. Toast notification → Recoverable errors, user can retry
3. Error banner → Page-level errors, data still partially usable
4. Full error screen → Unrecoverable, needs user action
CRITICAL: Never swallow errors silently.
// CORRECT - Error always surfaced to user
const [createItem, { loading }] = useCreateItemMutation({
onCompleted: () => {
toast.success({ title: 'Item created' });
},
onError: (error) => {
console.error('createItem failed:', error);
toast.error({ title: 'Failed to create item' });
},
});
// WRONG - Error silently caught, user has no idea
const [createItem] = useCreateItemMutation({
onError: (error) => {
console.error(error); // User sees nothing!
},
});
interface ErrorStateProps {
error: Error;
onRetry?: () => void;
title?: string;
}
const ErrorState = ({ error, onRetry, title }: ErrorStateProps) => (
{title ?? 'Something went wrong'}
{error.message}
{onRetry && (
Try Again
)}
);
Submit
CRITICAL: Always disable triggers during async operations.
// CORRECT - Button disabled while loading
Submit
// WRONG - User can tap multiple times
{isSubmitting ? 'Submitting...' : 'Submit'}
Every list/collection MUST have an empty state:
// WRONG - No empty state
return ;
// CORRECT - Explicit empty state
return (
}
/>
);
// Search with no results
// List with no items yet
const MyForm = () => {
const [submit, { loading }] = useSubmitMutation({
onCompleted: handleSuccess,
onError: handleError,
});
const handleSubmit = async () => {
if (!isValid) {
toast.error({ title: 'Please fix errors' });
return;
}
await submit({ variables: { input: values } });
};
return (
Submit
);
};
// WRONG - Spinner when data exists (causes flash)
if (loading) return ;
// CORRECT - Only show loading without data
if (loading && !data) return ;
// WRONG - Error swallowed
try {
await mutation();
} catch (e) {
console.log(e); // User has no idea!
}
// CORRECT - Error surfaced
onError: (error) => {
console.error('operation failed:', error);
toast.error({ title: 'Operation failed' });
}
// WRONG - Button not disabled during submission
Submit
// CORRECT - Disabled and shows loading
Submit
Before completing any UI component:
UI States:
Data & Mutations:
Install via CLI
npx mdskills install sickn33/react-ui-patternsReact UI Patterns is a free, open-source AI agent skill. Modern React UI patterns for loading states, error handling, and data fetching. Use when building UI components, handling async data, or managing UI states.
Install React UI Patterns with a single command:
npx mdskills install sickn33/react-ui-patternsThis downloads the skill files into your project and your AI agent picks them up automatically.
React UI Patterns works with Claude Code, Claude Desktop, Cursor, Vscode Copilot, Windsurf, Continue Dev, Codex, Gemini Cli, Amp, Roo Code, Goose, Opencode, Trae, Qodo, Command Code. Skills use the open SKILL.md format which is compatible with any AI coding agent that reads markdown instructions.