Compositionの意図が不明瞭なコンポーネント構造
はじめに
「見た目は一貫してるけど、何のためにこう分かれてるのかが分からない」
そんな感覚に陥るReact構造は、大抵Compositionの意図が曖昧です。
コンポーネントを合成して構築するスタイルはReactの強みですが、合成の粒度や責務、抽象化の目的が不明瞭なままでは、かえって読みづらく、レビューや保守を困難にしてしまいます。
この記事では、レビューアーとしてComposition構造をどう読み取り、どのように整理・改善提案していくかを具体的に解説します。
よくある「意図不明な合成」の例
例1:ただの断片が積み重なった構造
Compositionが断片化している例
export function Dashboard() {
return (
<Wrapper>
<TopRow />
<MainContent />
<GraphContainer />
<SettingsPanel />
</Wrapper>
);
}
構文的には正しいですが、これだけでは以下のような不明点が残ります。
TopRow
とMainContent
はどのような関係?Wrapper
の責務は? レイアウト? ロジックの注入?GraphContainer
が状態を持っているのか、表示だけなのか分からない
例2:Compositionがコンテキスト依存でブラックボックス化
<SomeProvider>
<SomeComponent />
</SomeProvider>
- Providerの中身や何を注入しているかが分からない
SomeComponent
が受け取る依存が暗黙的
Composition構造が不明瞭になる理由
原因 | 解説 |
---|---|
意図の異なる構造を並列配置している | 表示目的/制御目的/状態保持が混ざる |
名前が抽象的すぎる | Wrapper , Container , Block など曖昧な名称 |
Provider構造が過剰または隠蔽的 | 何を使っているのかコードから分からない |
子要素構造を前提にしている | props.children を使っているが、使われ方が文書化されていない |
レビューで確認したいチェックポイント
改善パターン
パターン1:Layout vs Logic を明確に分ける
return (
<DashboardLayout>
<UserGraphSection />
<RecentLogList />
</DashboardLayout>
);
DashboardLayout
は純粋にUIの配置(PaddingやGrid)に責務を限定- 各セクションごとに状態を持たせる or 別Containerで状態保持する
パターン2:明示的な役割に基づいた命名を行う
- <Wrapper>
+ <DashboardLayout>
- <Container>
+ <UserInfoFetcher>
レビュー時には、名前が抽象的すぎてその役割が推測できない場合は、命名の再検討を強く推奨すべきです。
パターン3:子要素の合成契約を明示する
正しいchildrenの使い方
export function Card({ children }: { children: ReactNode }) {
return <div className="card">{children}</div>;
}
<Card>
<Card.Title>タイトル</Card.Title>
<Card.Body>内容</Card.Body>
</Card>
これを使う側にとっても分かりやすく、構造としても一貫性があります。
レビューでは children構造があるとき、明示的な合成意図があるかどうか をチェックしましょう。
構造比較(意図不明 vs 明確化)
明確な役割と意図に基づいた合成構造に変えることで、階層も構造も理解しやすくなります。
コメント例(レビュー時)
Comment
@Reviewer: 合成されたコンポーネントの命名と責務が一致しておらず、構造の意図が読み取りづらくなっています。Layout系はUI配置に限定し、状態保持系はContainer分離を検討すると明瞭になります。
- <Wrapper>
+ <DashboardLayout>
まとめ
CompositionはReactにおける柔軟な設計手法ですが、その意図がコードから読み取れなければ、柔軟性は“わかりづらさ”に変わってしまいます。
レビューアーの視点では、
- 命名と責務の整合
- 合成の前提が明示されているか
- 親→子の構造が適切に分離されているか
を重視しながら、「この構造は誰のためのものか?」という問いを繰り返すことで、Compositionの質と意図を引き出すレビューが可能になります。