React Ui Patterns

作者 davila78da17d671b6f無授權條款32K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫今天更新

Modern React UI patterns for loading states, error handling, and data fetching. Use when building UI components, handling async data, or managing UI states.

AI 產生的概覽

提供 React UI 模式指南,涵蓋載入狀態、錯誤處理、空狀態與表單提交。

功能
此技能為建構 React UI 元件提供參考指南與程式碼範例,統一處理載入、錯誤、空狀態與按鈕狀態。內容包括何時使用載入指示器與骨架畫面的決策樹、錯誤處理層級,以及呈現錯誤與在非同步操作期間停用按鈕的模式。它產出的是指導性內容與範例片段,而非可執行程式碼。
適用情境
適用於在 React 應用中建構 UI 元件、處理非同步資料擷取或管理 UI 狀態時。也適合在檢視元件是否缺少錯誤、載入或空狀態時使用。
執行需求
無需指令碼或工具,僅為說明性內容。範例涉及 React、TypeScript 與 GraphQL 風格的鉤子,但閱讀指南不需要安裝任何套件或提供認證資訊。

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 existsconst { 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 dataif (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 WhenUse Spinner When
Known content shapeUnknown content shape
List/card layoutsModal actions
Initial page loadButton submissions
Content placeholdersInline operations

Error Handling Patterns

The Error Handling Hierarchy

1. Inline error (field-level) → Form validation errors2. Toast notification → Recoverable errors, user can retry3. Error banner → Page-level errors, data still partially usable4. Full error screen → Unrecoverable, needs user action

Always Show Errors

CRITICAL: Never swallow errors silently.

typescript
// CORRECT - Error always surfaced to userconst [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 ideaconst [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 statereturn <FlatList data={items} />;
// CORRECT - Explicit empty statereturn (  <FlatList    data={items}    ListEmptyComponent={<EmptyState />}  />);

Contextual Empty States

tsx
// 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

tsx
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 (    <form>      <Input        value={values.name}        onChange={handleChange('name')}        error={touched.name ? errors.name : undefined}      />      <Button        type="submit"        onClick={handleSubmit}        disabled={!isValid || loading}        isLoading={loading}      >        Submit      </Button>    </form>  );};

Anti-Patterns

Loading States

typescript
// WRONG - Spinner when data exists (causes flash)if (loading) return <Spinner />;
// CORRECT - Only show loading without dataif (loading && !data) return <Spinner />;

Error Handling

typescript
// WRONG - Error swallowedtry {  await mutation();} catch (e) {  console.log(e); // User has no idea!}
// CORRECT - Error surfacedonError: (error) => {  console.error('operation failed:', error);  toast.error({ title: 'Operation failed' });}

Button States

typescript
// 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

來源與署名

來源:davila7/claude-code-templates位於cli-tool/components/skills/development/react-ui-patterns提交8da17d6

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架