generic-react-code-reviewer について
React と TypeScript のコードを本番品質の基準で確認する開発者向けレビュースキルです。型安全性、コンポーネントと状態管理、パフォーマンス、アクセシビリティを重視し、diff の読み取りによる検証を勧めます。
主な機能
- 01TypeScript 厳格モードの確認
- 02コンポーネントと Hook 依存関係の確認
- 03状態管理の型確認
- 04クエリのキャッシュとエラー処理の確認
- 05パフォーマンスとアクセシビリティのレビュー
活用シーン
- 01コミット前の React diff レビュー
- 02Hook 依存関係と状態の型の確認
- 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 を使用していない |
| State | Zustand/useState で型付けされている |
| Events | イベントハンドラーが型付けされている |
| Refs | useRef<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 の依存関係が正しい
- 重いコンポーネントが遅延読み込みされている
- 状態管理が型付けされている
- 効果的な箇所でメモ化されている
- モーダルでフォーカスが管理されている
関連項目
- 汎用コードレビュアー — ベースとなるレビュー手法
- コードレビュー基準 — セキュリティ/パフォーマンス/アクセシビリティの全項目
- デザインパターン — UI の一貫性
コメント
Markdown 対応