mcpField
R
react-best-practices

react-best-practices

github.com/pixel-process-ug開発379 回インストール34 週間前に更新
リポジトリ

react-best-practices について

react-best-practicesは、保守しやすくテスト可能なアプリを作るためのReact向けスキルです。React 18/19のパターン、コンポーネント設計、テスト、計測に基づく最適化を扱います。

主な機能

  1. 01サーバー/クライアントコンポーネントの選択
  2. 02フックとコンポーネント合成パターン
  3. 03エラーバウンダリーとSuspense
  4. 04コンテキストと描画の最適化
  5. 05アクセシビリティを考慮した動作テスト

活用シーン

  1. 01コンポーネントのデータと状態の境界設定
  2. 02再利用可能なReactコンポーネントの設計
  3. 03読み込み・エラー・操作状態のテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill react-best-practices

インストール後、Claude Code で/react-best-practicesを入力して読み込まれたか確認します。

詳細

React のベストプラクティス

概要

最新の React パターンを適用し、保守性、パフォーマンス、テスト性に優れたアプリケーションを構築します。このスキルでは、Server Components、フックのベストプラクティス、コンポーネントのコンポジション、エラーバウンダリ、Suspense、コンテキストの最適化、レンダリングパフォーマンスなど、React 18/19 の機能を扱います。React に特化した詳しい内容を提供し、senior-frontend スキルを補完します。

開始時に宣言:「React 固有のパターンに react-best-practices スキルを使用します。」


フェーズ 1:コンポーネントの要件を分析する

目標: コーディングを始める前に、コンポーネントの責務とデータ要件を理解します。

アクション
  1. コンポーネントの単一の責務を特定する
  2. データ要件を判断する(サーバーデータかクライアントデータか)
  3. Server Component(デフォルト)か Client Component を選択する
  4. 状態管理の要件を特定する
  5. エラー状態と読み込み状態を計画する
サーバーとクライアントの判断表
要件コンポーネントの種類理由
直接のデータ取得(DB、API)Server(デフォルト)クライアント JS が不要で、より高速
イベントハンドラー(onClick、onChange)Client('use client')ブラウザーでのインタラクティブ性が必要
useState / useReducerClient状態にはクライアントランタイムが必要
useEffect / useLayoutEffectClient副作用にはクライアントが必要
ブラウザー API(window、localStorage)Clientサーバーにはブラウザーがない
クライアント機能を使用するサードパーティーライブラリClientライブラリにクライアントが必要
インタラクティブ性が不要Server(デフォルト)バンドルが小さくなり、より高速
停止 — 次の項目を満たすまでフェーズ 2 に進まないでください:
  • コンポーネントの責務(単一の目的)が定義されている
  • 理由を明確にして Server と Client のどちらにするか決定している
  • データ要件が整理されている

フェーズ 2:適切なパターンで実装する

目標: コンポーネントの要件に適した React パターンを適用します。

アクション
  1. 適切なコンポジションパターンを適用する
  2. フックを正しく実装する
  3. エラーバウンダリと Suspense を追加する
  4. プロファイリングで必要性が確認された場合に、レンダリングを最適化する
  5. 動作を検証するテストを書く
停止 — 次の項目を満たすまでフェーズ 3 に進まないでください:
  • パターンがコンポーネントの実際の要件に合っている
  • 不要な複雑さがない(早すぎる最適化をしていない)
  • ユーザーに見える動作をテストでカバーしている

フェーズ 3:テストと検証を行う

目標: テストを通じてコンポーネントの動作を検証します。

アクション
  1. アクセシブルなクエリを使ってテストを書く
  2. ユーザーの操作とその結果をテストする
  3. エラー状態と読み込み状態をテストする
  4. アクセシビリティを検証する
クエリの優先順位(React Testing Library)
優先順位クエリ用途
1 番目getByRoleARIA ロールを持つすべての要素
2 番目getByLabelTextフォームフィールド
3 番目getByPlaceholderTextラベルのないフィールド
4 番目getByTextインタラクティブでない要素
最後getByTestIdほかの方法が使えない場合
停止 — 次の項目を満たしたらテスト完了です:
  • ユーザーの操作によって期待どおりの結果が得られる
  • エラー状態がテストされている
  • アクセシビリティチェックに合格している

フックのベストプラクティス

useState
// Functional updates for state based on previous state
setCount(prev => prev + 1);

// Lazy initialization for expensive initial values
const [data, setData] = useState(() => computeExpensiveInitialValue());

// Group related state
const [form, setForm] = useState({ name: '', email: '', role: 'user' });
useEffect
依存配列のルール
  • 時間の経過とともに変化するコンポーネントスコープ内の値をすべて含める
  • エフェクト内で使う関数は、エフェクト内で定義するか、useCallback でラップする
  • 依存関係を偽ってはいけない(ESLint:react-hooks/exhaustive-deps)
クリーンアップのパターン
useEffect(() => {
  const controller = new AbortController();
  async function fetchData() {
    try {
      const res = await fetch(url, { signal: controller.signal });
      const data = await res.json();
      setData(data);
    } catch (e) {
      if (e.name !== 'AbortError') setError(e);
    }
  }
  fetchData();
  return () => controller.abort();
}, [url]);
useEffect を使用しない場合
useEffect の代わりに使う用途使用するもの
データの取得React Query、SWR、または Server Components
データの変換レンダリング中に計算する
ユーザーイベントイベントハンドラー
外部ストアとの同期useSyncExternalStore
カスタムフックのルール
  • 名前は use で始める
  • 再利用可能な状態付きロジックをカプセル化する
  • 1 つの関心事につき 1 つのフックを作る
  • 値が 2 つを超える場合は、配列ではなくオブジェクトを返す
function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);
  return debouncedValue;
}

コンポーネントのコンポジションパターン

複合コンポーネント
function Tabs({ children, defaultValue }: TabsProps) {
  const [activeTab, setActiveTab] = useState(defaultValue);
  return (
    <TabsContext.Provider value={{ activeTab, setActiveTab }}>
      <div role="tablist">{children}</div>
    </TabsContext.Provider>
  );
}

Tabs.Tab = function Tab({ value, children }: TabProps) {
  const { activeTab, setActiveTab } = useTabsContext();
  return (
    <button role="tab" aria-selected={activeTab === value} onClick={() => setActiveTab(value)}>
      {children}
    </button>
  );
};

Tabs.Panel = function Panel({ value, children }: PanelProps) {
  const { activeTab } = useTabsContext();
  if (activeTab !== value) return null;
  return <div role="tabpanel">{children}</div>;
};
コンポジションの判断表
パターン使用する場面例
複合コンポーネント関連するコンポーネントが暗黙的な状態を共有する場合タブ、アコーディオン、メニュー
スロット(子要素)複雑なコンテンツレイアウトの場合ヘッダー/本文/フッターを備えたカード
レンダープロップ柔軟なレンダリングのために子要素が親のデータを必要とする場合カスタムレンダーを備えた DataFetcher
高階コンポーネント横断的な関心事(レガシー)の場合withAuth、withTheme
カスタムフックUI を伴わない、再利用可能な状態管理ロジックの場合useDebounce、useLocalStorage
スロットパターン
// Prefer composition over props for complex content
// Bad
<Card title="Hello" subtitle="World" icon={<Star />} actions={<Button>Edit</Button>} />

// Good
<Card>
  <Card.Header>
    <Card.Icon><Star /></Card.Icon>
    <Card.Title>Hello</Card.Title>
  </Card.Header>
  <Card.Actions>
    <Button>Edit</Button>
  </Card.Actions>
</Card>

エラーバウンダリー

配置戦略の判断表
レベル目的例
ルートレベルページレベルのクラッシュを捕捉するNext.js の error.tsx
機能レベル機能の障害を分離する各主要セクションをラップする
データレベル非同期データコンポーネントをラップするSuspense 境界の周囲
リーフレベルには配置しない粒度が細かすぎて、ノイズが増える個々のボタンはラップしない

Suspense

// Nested Suspense for granular loading
<Suspense fallback={<PageSkeleton />}>
  <Header />
  <Suspense fallback={<SidebarSkeleton />}>
    <Sidebar />
  </Suspense>
  <Suspense fallback={<ContentSkeleton />}>
    <MainContent />
  </Suspense>
</Suspense>

Context の最適化

問題:Context が不要な再レンダリングを引き起こす
解決策の判断表
手法使用する場面例
更新頻度ごとに Context を分割する頻繁に更新される値と、まれに更新される値がある場合ThemeContext(まれ)と UIStateContext(頻繁)
Context の値をメモ化する同じデータで Provider が再レンダリングされる場合useMemo(() => ({ state, dispatch }), [state])
セレクターを使用する(Zustand/Jotai)細粒度のサブスクリプションが必要な場合useStore(state => state.user.name)
状態を上位に持ち上げる親だけを再レンダリングする必要がある場合データをメモ化した子要素に props として渡す

レンダリングの最適化

メモ化の判断表
手法使用する場面使用しない場面
React.memo同じ props で頻繁にレンダリングされ、かつ再レンダリングのコストが高い場合props がレンダリングのたびに変わる場合
useMemo計算コストが高い場合、または依存値の参照同一性が必要な場合単純な計算の場合
useCallbackメモ化された子要素のために関数参照を安定させる場合関数を props として渡さない場合
なし(デフォルト)常にここから始める時期尚早な最適化

ルール: メモ化する前にプロファイリングしてください。時期尚早なメモ化は、React で最もよくあるアンチパターンです。

仮想化

100 件を超えるリストの場合:

import { useVirtualizer } from '@tanstack/react-virtual';

サーバーコンポーネントのルール

  • フックは使用できません
  • ブラウザー API は使用できません
  • Client Components に props として関数を渡すことはできません
  • Client Components をインポートしてレンダリングすることはできます
  • シリアライズ可能なデータを Client Components に渡すことはできます
// Server Component — fetches data directly
async function UserProfile({ userId }: { userId: string }) {
  const user = await db.user.findUnique({ where: { id: userId } });
  return (
    <div>
      <h1>{user.name}</h1>
      <UserActions userId={userId} /> {/* Client Component child */}
    </div>
  );
}

// Client Component — handles interactivity
'use client';
function UserActions({ userId }: { userId: string }) {
  const [isFollowing, setIsFollowing] = useState(false);
  return <Button onClick={() => toggleFollow(userId)}>Follow</Button>;
}

アンチパターン/よくある間違い

アンチパターン問題点正しい方法
データ取得に useEffect を使用する競合状態が発生し、キャッシュも重複排除もできないReact Query または Server Components を使用する
2 レベルを超える props のバケツリレー密結合になり、保守が困難になるコンポジション、Context、または Zustand を使用する
派生状態を保存する計算できる状態は不要な状態であるレンダリング中に計算する
props から状態を同期するために useEffect を使用する不要なエフェクトと古いクロージャーが発生するレンダリング中に導出するか、key prop を使用する
巨大なコンポーネント(200 行超)読みづらく、テストや保守が困難になるサブコンポーネントを切り出す
動的リストの key にインデックスを使用する誤った再調整や古い状態が発生する安定した一意の ID を使用する
DOM を直接操作するReact の再調整を迂回するref は控えめに使い、状態を優先する
状態値を直接テストする実装の詳細に依存し、リファクタリングで壊れるユーザーに見える結果をテストする
すべてをメモ化する複雑さが増し、かえって遅くなることが多いまずプロファイリングし、その後に最適化する

ドキュメントの検索(Context7)

最新のドキュメントを参照するには、mcp__context7__resolve-library-id、続いて mcp__context7__query-docs を使用してください。取得したドキュメントは、記憶している知識より優先されます。

  • react — フック、Context、Suspense、サーバーコンポーネント、または React 19 以降の変更について
  • next.js — App Router のパターン、データ取得、またはサーバーアクションについて

統合ポイント

スキル関連性
senior-frontendフロントエンドスキルでは、このスキルの React パターンを使用します
testing-strategyReact のテストでは、戦略ピラミッドに従います
clean-codeコンポーネントのコードでは、クリーンコードの原則に従います
performance-optimizationReact のレンダリング最適化では、測定方法に従います
webapp-testingE2E テストで React コンポーネントの動作を検証します
code-reviewレビューで React のアンチパターンを確認します
acceptance-testingUI の受け入れ基準をもとに、コンポーネントのテストを作成します

スキルの種類

FLEXIBLE — 使用する React のバージョン、プロジェクト構成、チームの慣習に応じて、これらのパターンを適用してください。原則は一貫していますが、実装の詳細は異なる場合があります。最適化の前に、必ずプロファイリングを行ってください。

コメント