コンポーネント設計
単一責任・再利用性・コンポジションを軸としたフロントエンドコンポーネントの分割・インターフェース設計
コンポーネント設計は、フロントエンドにおいてバックエンドのクラス設計と同等の重要性を持つ。適切に設計されたコンポーネントは再利用可能で変更容量が小さく、テストが容易になる。一方で過度に大きなコンポーネントは、複数の責務が混在してビジネスロジックとUIの変更が干渉し合い、保守が困難になる。
Presentational / Containerパターン(Smart / Dumbコンポーネントとも呼ばれる)は、データ取得・状態管理などのロジックを持つContainerコンポーネントと、受け取ったPropsを表示するだけのPresentationalコンポーネントに分離する設計パターンである。PresentationalコンポーネントはPropsに対して純粋なレンダリングを行うため、Storybookでの確認やユニットテストが容易になる。ReactではHooksの導入によってロジックをカスタムHookに切り出すことで、このパターンをより柔軟に実現できるようになっている。
コンポーネントのProps APIの設計はPublic APIの設計と同様に慎重に行う必要がある。一度公開したPropsは呼び出し元の変更コストなしには削除・変更できないため、最小限のPropsから始めて必要に応じて拡張する「YAGNI(You Aren’t Gonna Need It)」的なアプローチが有効である。コンポジション(Composition)パターンではchildrenやRender Propsを通じて、コンポーネントの内部実装を知らなくても柔軟にカスタマイズできるインターフェースを提供する。
コードレビューで着目するポイント
- コンポーネントが単一の責務を持っているか(データ取得・ビジネスロジック・表示が1ファイルに混在していないか)
- Prop drillingが3層以上にわたっていないか(Context APIやZustand等への移行を検討すべきサイン)
- 制御コンポーネント(Controlled)と非制御コンポーネント(Uncontrolled)の使い分けが意図的か
- コンポーネントのProps定義がTypeScriptで厳密に型付けされているか(
anyや不必要なオプショナルが含まれていないか) childrenやrenderPropsを活用したコンポジション設計が、継承ではなく組み合わせで柔軟性を実現しているか- カスタムHookにロジックが適切に切り出されており、コンポーネント内の処理が最小限か
- 副作用(
useEffect)の依存配列が正確に管理されているか
典型的なアンチパターン
God Component: 一つのコンポーネントファイルにデータ取得・状態管理・フォームバリデーション・表示ロジックがすべて詰め込まれた500行超のコンポーネント。変更の影響範囲が予測できず、テストも困難になる。ロジックをカスタムHookに、表示をPresentationalコンポーネントに分割すべきである。
Prop drilling地獄: 最上位のコンポーネントが持つデータを5階層下のコンポーネントに渡すために、中間の全コンポーネントが不要なPropsを受け取る設計。Context APIやグローバル状態管理でデータを適切なスコープで管理することで解消できる。
継承によるコンポーネント拡張: ベースコンポーネントを継承(extend)して機能を追加するアプローチは、Reactのコンポーネントモデルには適合しない。childrenPropsやrenderProps、カスタムHookの組み合わせによるコンポジションで柔軟性を実現するのが正しい設計方針である。
参考リソース
- 公式ドキュメント: React Composition vs Inheritance - Reactの公式ドキュメントによるコンポジション設計のガイド
- 書籍: 「Learning Patterns」(Lydia Hallie, Addy Osmani) - フロントエンドのデザインパターンをインタラクティブに学べる無料オンライン書籍
- ツール: Storybook - コンポーネントのインターフェース設計を視覚的に検証するための標準ツール
- パターン: Container/Presentational Pattern - Smart/Dumbコンポーネント分離パターンの解説
- ツール: React DevTools - コンポーネント階層とProps/State のデバッグツール
- 1. 📄アーキテクチャスタイル
- 2. 📄ドメインモデリング
- 3. 📄モジュール分割と依存管理
- 4. 📄データモデリング
- 5. 📄API設計
- 6. 📄整合性とトランザクション
- 7. 📄非同期処理(Queue/Event)
- 8. 📄キャッシング
- 9. 📄ユーザーリサーチ
- 10. 📄情報アーキテクチャ
- 11. 📄インタラクションデザイン
- 12. 📄UX原則とヒューリスティクス
- 13. 📄アクセシビリティ(UX観点)
- 14. 📄UXメトリクス
- 15. 📄スケーラビリティ
- 16. 📄可用性とレジリエンス
- 17. 📄オブザーバビリティ
- 18. 📄環境・インフラ設計
- 19. 📄データマイグレーション
- 20. 📄セキュリティ設計原則
- 21. 📄データ保護とマルチテナント
- 22. 📄LLMセキュリティ
- 23. 📄ビジュアルデザイン原則
- 24. 📄デザインシステム
- 25. 📄コンポーネント設計
- 26. 📄スタイリング
- 27. 📄設計原則
- 28. 📄デザインパターン(GoF)
- 29. 📄エンタープライズパターン
- 30. 📄クリーンコード
- 31. 📄リファクタリング
- 32. 📄型設計とコントラクト
- 33. 📄関数型プログラミング概念
- 34. 📄エラーハンドリング
- 35. 📄テスト戦略と哲学
- 36. 📄テスト種別(機能テスト)
- 37. 📄テスト種別(UI・ビジュアル)
- 38. 📄テスト種別(契約・境界)
- 39. 📄並行処理・マルチスレッド
- 40. 📄パフォーマンス最適化
- 41. 📄ドキュメント管理
- 42. 📄バージョン管理と開発プロセス
- 43. 📄脅威モデリング
- 44. 📄通信保護(TLS)
- 45. 📄暗号化・機密情報管理
- 46. 📄認証・セッション管理
- 47. 📄認可・アクセス制御
- 48. 📄入力バリデーション
- 49. 📄インジェクション攻撃
- 50. 📄正規化(データベース正規化)