react-ui-patterns – skill Thiết kế & UI cho agent AI
Các mẫu UI React hiện đại cho trạng thái loading, xử lý lỗi và lấy dữ liệu. Dùng khi xây dựng component UI, xử lý dữ liệu bất đồng bộ hoặc quản lý trạng thái giao diện.
Cài skill react-ui-patterns bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/react-ui-patterns-80fcb.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /react-ui-patterns – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/react-ui-patterns-80fcb.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $react-ui-patterns – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/react-ui-patterns-80fcb.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /react-ui-patterns – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/react-ui-patterns-80fcb.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /react-ui-patterns – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
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.
// CORRECT - Only show loading when no data exists
const { data, loading, error, refetch } = 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} />;// 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 actionAlways Show Errors
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!
},
});Error State Component Pattern
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>Unable to load this content. Try again if the problem persists.</p>
{onRetry && (
<Button onClick={onRetry}>Try Again</Button>
)}
</div>
);Button State Patterns
Button Loading State
<Button
onClick={handleSubmit}
isLoading={isSubmitting}
disabled={!isValid || isSubmitting}
>
Submit
</Button>Disable During Operations
CRITICAL: Always disable triggers during async operations.
// 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:
// WRONG - No empty state
return <FlatList data={items} />;
// CORRECT - Explicit empty state
return (
<FlatList
data={items}
ListEmptyComponent={<EmptyState />}
/>
);Contextual Empty States
// Search with no results
<EmptyState
icon="search"
title="No results found"
description="Try different search terms"
/>
// List with no items yet
<EmptyState
icon="plus-circle"
title="No items yet"
description="Create your first item"
action={{ label: 'Create Item', onClick: handleCreate }}
/>Form Submission Pattern
const MyForm = () => {
const [submit, { loading }] = useSubmitMutation({
onCompleted: handleSuccess,
onError: handleError,
});
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
if (!isValid) {
toast.error({ title: 'Please fix errors' });
return;
}
await submit({ variables: { input: values } });
};
return (
<form onSubmit={handleSubmit}>
<Input
value={values.name}
onChange={handleChange('name')}
error={touched.name ? errors.name : undefined}
/>
<Button
type="submit"
disabled={!isValid || loading}
isLoading={loading}
>
Submit
</Button>
</form>
);
};Anti-Patterns
Loading States
// WRONG - Spinner when data exists (causes flash)
if (loading) return <Spinner />;
// CORRECT - Only show loading without data
if (loading && !data) return <Spinner />;Error Handling
// 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' });
}Button States
// WRONG - Button not disabled during submission
<Button onClick={submit}>Submit</Button>
// CORRECT - Disabled and shows loading
<Button onClick={submit} disabled={loading} isLoading={loading}>
Submit
</Button>Checklist
Before completing any UI component:
UI States:
- [ ] Error state handled and shown to user
- [ ] Loading state shown only when no data exists
- [ ] Empty state provided for collections
- [ ] Buttons disabled during async operations
- [ ] Buttons show loading indicator when appropriate
Data & Mutations:
- [ ] Mutations have onError handler
- [ ] All user actions have feedback (toast/visual)
Integration with Other Skills
- graphql-schema: Use mutation patterns with proper error handling
- testing-patterns: Test all UI states (loading, error, empty, success)
- formik-patterns: Apply form submission patterns
When to Use
This skill is applicable to execute the workflow or actions described in the overview.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
Skill liên quan
- redesign-existing-projects – Dùng khi nâng cấp website hoặc ứng dụng hiện có bằng cách kiểm tra các mẫu UI chung…
- retro-design – Hướng dẫn triển khai Web và App cho Retro Design (thập niên 60-80). Kích hoạt khi người…
- retro-futurism – Hướng dẫn triển khai Web và App cho Retro Futurism. Kích hoạt khi người dùng muốn ý…
- reverse-image-search – Tìm kiếm ngược hình ảnh. Dùng khi làm việc với hình ảnh hoặc URL hình ảnh công khai.
- robius-state-management – CRITICAL: Dùng cho các mẫu quản lý trạng thái của Robius. Kích hoạt khi có: AppState…
- robius-widget-patterns – CRITICAL: Dùng cho các mẫu widget của Robius. Kích hoạt khi có: apply_over, TextOrImage…
- saas-multi-tenant – Thiết kế và triển khai kiến trúc SaaS đa khách hàng (multi-tenant) với row-level…
- scarcity-urgency-psychologist – Thiết kế thông điệp về sự khan hiếm và tính cấp bách một cách trung thực, khi tồn kho…