mcpField
G
generic-react-code-reviewer

generic-react-code-reviewer

github.com/travisjneumanテスト・品質106143 回インストール1 日前に更新
リポジトリ

generic-react-code-reviewer について

React と TypeScript のコードを本番品質の基準で確認する開発者向けレビュースキルです。型安全性、コンポーネントと状態管理、パフォーマンス、アクセシビリティを重視し、diff の読み取りによる検証を勧めます。

主な機能

  1. 01TypeScript 厳格モードの確認
  2. 02コンポーネントと Hook 依存関係の確認
  3. 03状態管理の型確認
  4. 04クエリのキャッシュとエラー処理の確認
  5. 05パフォーマンスとアクセシビリティのレビュー

活用シーン

  1. 01コミット前の React diff レビュー
  2. 02Hook 依存関係と状態の型の確認
  3. 03遅延読み込み、キャッシュ、フォーカス管理のレビュー

インストール

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

$npx skills add https://github.com/travisjneuman/.claude --skill generic-react-code-reviewer

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

詳細

React コードレビュアー

本番品質の基準に照らして、React/TypeScript のコードをレビューします。

拡張元: 汎用コードレビュアー — コードレビューの全手法、P0/P1/P2 の優先度システム、判断が必要なケースについては、ベーススキルをお読みください。

コミット前の検証

テスト/Lint/ビルドを順に実行するのではなく、差分を読んで検証してください。以下は確認すべき項目です。

React 固有のチェック

TypeScript の Strict モード
// Required tsconfig.json settings
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}
  • ユーザー入力や API レスポンスに any 型を使用しない
  • 外部データはまず unknown として検証し、その後に型ガードを使用する
  • 再利用可能なユーティリティでは any よりジェネリック型を使用する
コンポーネントのパターン
パターンチェック項目
Propsインターフェースが定義されており、any を使用していない
StateZustand/useState で型付けされている
Eventsイベントハンドラーが型付けされている
RefsuseRef<ElementType>(null)
Hook の依存配列
// P1 Issue: Missing dependencies
useEffect(() => {
  fetchData(userId); // userId missing from deps
}, []); // ❌

// Correct
useEffect(() => {
  fetchData(userId);
}, [userId]); // ✓

ルール: ESLint ルール react-hooks/exhaustive-deps を有効にしてください。

状態管理(Zustand/Redux)
  • ストアのスライスが適切に型付けされている
  • アクションは void を返す(状態を直接更新する)
  • 派生状態のセレクターはメモ化されている
  • 大きなデータ(>1MB)は localStorage ではなく IndexedDB に保存する
React Query/SWR のパターン
// Proper typing
const { data } = useQuery<User>({
  queryKey: ["user", id],
  queryFn: () => fetchUser(id),
});

// Check: staleTime, cacheTime configured
// Check: error boundaries for query failures

パフォーマンス(P1)

バンドルサイズの目標値
目標しきい値
初期バンドルgzip 圧縮後 < 100KB
遅延読み込みされるチャンクそれぞれ < 50KB
JS の合計< 300KB
遅延読み込み
// Heavy components (>20KB) MUST be lazy loaded
const HeavyChart = lazy(() => import('./HeavyChart'));
const RichTextEditor = lazy(() => import('./RichTextEditor'));

// Wrap in Suspense
<Suspense fallback={<Skeleton />}>
  <HeavyChart />
</Suspense>
メモ化
// Expensive calculations
const sortedItems = useMemo(() =>
  items.sort((a, b) => a.date - b.date),
  [items]
);

// Callback stability for child components
const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

// Component memoization (when props are stable)
export const Item = memo(function Item({ data }: Props) {
  return <div>{data.name}</div>;
});
アニメーション(GPU アクセラレーションのみ)
/* ✓ DO animate */
transform: translateY(-4px);
opacity: 0.5;

/* ❌ NEVER animate */
width, height, margin, padding, top, left

アクセシビリティ(P1)

フォーカス管理
// Modal focus trapping
useEffect(() => {
  if (isOpen) {
    const firstFocusable = modalRef.current?.querySelector("button, input");
    firstFocusable?.focus();
  }
}, [isOpen]);

// Escape to close
useEffect(() => {
  const handleEscape = (e: KeyboardEvent) => {
    if (e.key === "Escape") onClose();
  };
  window.addEventListener("keydown", handleEscape);
  return () => window.removeEventListener("keydown", handleEscape);
}, [onClose]);
JSX での ARIA
// Icon-only buttons require labels
<button aria-label="Close modal">
  <X className="w-5 h-5" />
</button>

// Dialogs
<div role="dialog" aria-modal="true" aria-labelledby="title">
  <h2 id="title">Confirm Action</h2>
</div>

クイックレビューチェックリスト

React 固有(ベースのチェックリストに追加):

  • Hook の依存関係が正しい
  • 重いコンポーネントが遅延読み込みされている
  • 状態管理が型付けされている
  • 効果的な箇所でメモ化されている
  • モーダルでフォーカスが管理されている

関連項目

コメント