
React Ui Patterns
Install when building React screens so loading, errors, empty states, and async data fetching feel polished instead of flashing spinners.
Overview
react-ui-patterns is an agent skill most often used in Build (also Ship) that standardizes React loading, error, and data-fetch UI behavior for async views.
Install
npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill react-ui-patternsWhat is this skill?
- Golden rule: show loading only when loading and no cached data exists
- Five core principles including optimistic updates and progressive disclosure
- Explicit loading-state decision tree from error through empty to data render
- Patterns for never showing stale UI during refetch
- TypeScript-oriented examples for query hooks and list rendering
- 5 core UI principles documented
- Loading-state decision tree with error-first branching
Adoption & trust: 1.1k installs on skills.sh; 40.1k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your React app flashes full-page spinners on every refetch and hides failures until users complain.
Who is it for?
Indie SaaS frontends using React or TypeScript with client-side queries who want agent-guided refactors without adopting a new UI kit.
Skip if: Non-React stacks, design-system-only work with no data fetching, or teams that already enforce the same rules in a shared internal lint rulebook.
When should I use this skill?
Building UI components, handling async data, or managing UI states in React.
What do I get? / Deliverables
Screens follow a consistent decision tree so errors, empty, loading, and data states render predictably and refetches keep showing cached content.
- Refactored components following loading and error patterns
- Consistent empty and retry UX across async views
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Primary shelf is Build because the skill encodes component-level UI behavior during product implementation. frontend is where loading-state decision trees, optimistic updates, and error surfacing patterns apply directly in React code.
Where it fits
Refactor a settings page so refetch does not replace the whole list with a spinner.
Add retry affordances and empty states to a billing history table fed by GraphQL.
Audit dashboard routes for violations of the loading golden rule before release.
How it compares
Pattern cookbook for React UI states, not a component generator or Storybook substitute.
Common Questions / FAQ
Who is react-ui-patterns for?
Solo builders and small teams shipping React or TypeScript UIs with agents who need reliable async state handling without enterprise design ops.
When should I use react-ui-patterns?
Use when building UI components, handling async data, or managing UI states—during feature build in frontend work and again in ship review or perf passes before launch.
Is react-ui-patterns safe to install?
It is documentation-only patterns with no bundled executables; still review the Security Audits panel on this page before adding community skills to your agent.
SKILL.md
READMESKILL.md - React Ui Patterns
# React UI Patterns ## Core Principles 1. **Never show stale UI** - Loading spinners only when actually loading 2. **Always surface errors** - Users must know when something fails 3. **Optimistic updates** - Make the UI feel instant 4. **Progressive disclosure** - Show content as it becomes available 5. **Graceful degradation** - Partial data is better than no data ## Loading State Patterns ### The Golden Rule **Show loading indicator ONLY when there's no data to display.** ```typescript // CORRECT - Only show loading when no data exists const { data, loading, error } = useGetItemsQuery(); if (error) return <ErrorState error={error} onRetry={refetch} />; if (loading && !data) return <LoadingState />; if (!data?.items.length) return <EmptyState />; return <ItemList items={data.items} />; ``` ```typescript // WRONG - Shows spinner even when we have cached data if (loading) return <LoadingState />; // Flashes on refetch! ``` ### Loading State Decision Tree ``` 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) ``` ### Skeleton vs Spinner | 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 | ## Error Handling Patterns ### The Error Handling Hierarchy ``` 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 ``` ### Always Show Errors **CRITICAL: Never swallow errors silently.** ```typescript // 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! }, }); ``` ### Error State Component Pattern ```typescript interface ErrorStateProps { error: Error; onRetry?: () => void; title?: string; } const ErrorState = ({ error, onRetry, title }: ErrorStateProps) => ( <div className="error-state"> <Icon name="exclamation-circle" /> <h3>{title ?? 'Something went wrong'}</h3> <p>{error.message}</p> {onRetry && ( <Button onClick={onRetry}>Try Again</Button> )} </div> ); ``` ## Button State Patterns ### Button Loading State ```tsx <Button onClick={handleSubmit} isLoading={isSubmitting} disabled={!isValid || isSubmitting} > Submit </Button> ``` ### Disable During Operations **CRITICAL: Always disable triggers during async operations.** ```tsx // CORRECT - Button disabled while loading <Button disabled={isSubmitting} isLoading={isSubmitting} onClick={handleSubmit} > Submit </Button> // WRONG - User can tap multiple times <Button onClick={handleSubmit}> {isSubmitting ? 'Submitting...' : 'Submit'} </Button> ``` ## Empty States ### Empty State Requirements Every list/collection MUST have an empty state: ```tsx // WRONG - No empty state return <FlatList data={items} />; // CORRECT - Explicit empty state return ( <FlatList data={items} ListEmptyComponent={<EmptyS