「コンポーネントを小さくすればいい」という勘違いを正す。保守性を最大化するReact設計の極意
現場でコードレビューをしていると、必ずと言っていいほど直面する問題がある。それは「コンポーネント分割の基準」だ。
「とにかく小さく分ければ再利用性が上がる」というのは半分正解だが、半分は罠だ。過剰な分割はコンポーネントツリーの深さを増大させ、Propsのバケツリレー(Prop Drilling)という地獄への片道切符になる。
今日は、Reactの設計において「どこで切り、どう繋ぐべきか」という、実務レベルで最も重要な指針を話そう。
—
1. 「単一責任の原則 (SRP)」をReact流に解釈する
プログラミングの古典であるSRPをReactに当てはめるなら、「コンポーネントは一つの『役割』のみを持つべきだ」ということになる。
しかし、この「役割」の定義が曖昧だと迷走する。現場で僕が推奨するのは、コンポーネントを以下の3つのレイヤーで整理することだ。
- UI(Presentational)コンポーネント: 見た目だけを定義する(例:Button, Input, Card)。状態を持たず、Propsで全てを受け取る。
- ロジック(Container)コンポーネント: データの取得や状態管理を行う。
- 機能(Feature/Domain)コンポーネント: 特定のビジネスドメイン(例:UserProfile, ProductList)に依存する単位。
「再利用性」が必要なのはUIコンポーネントだけだ。ビジネスロジックが詰まったものを無理に再利用しようとすると、後で仕様変更があった際に地獄を見る。
—
2. 現場で使える「分割の判断基準」
コードを書く前に、以下のチェックリストを頭に入れておいてほしい。
1. レンダリング頻度: 親の再レンダリングに巻き込まれていないか?(React.memoで防ぐべき重い処理があるか)
2. コードの責務: そのコンポーネントは「データの加工」と「UIの描画」の両方をやっていないか?
3. 命名の難易度: 名前が `CommonComponent` や `SubPart` のように曖昧になっていないか?(名前が付けにくいのは、責務が混ざっている証拠だ)
—
3. 実践:クリーンなコンポーネント設計例
例えば、ユーザー情報を表示するカードを作る際、悪い例は全てを1つのファイルに書くことだ。これを「ロジック」と「UI」に分離してみよう。
// — UserCard.tsx (責務を分離した設計) —
import React from ‘react’;
// 1. UIコンポーネント: 見た目に集中する(純粋関数)
const UserProfileDisplay = ({ name, email }: { name: string, email: string }) => (
{name}
{email}
);
// 2. ロジックコンポーネント: データの取得や状態管理に集中する
export const UserCard = ({ userId }: { userId: string }) => {
// ここでAPIを叩くか、Contextからデータを引っ張ってくる
const [user, setUser] = React.useState(null);
React.useEffect(() => {
// データフェッチのロジック
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}, [userId]);
if (!user) return
;
// 3. 組み合わせる
return
};
なぜこの分割が良いのか?
- テスト容易性: `UserProfileDisplay` は純粋なUIなので、Storybookで簡単にビジュアルテストができる。モックデータさえ流し込めばOKだ。
- ブラウザの処理効率: `UserCard` で状態が変わっても、Reactの仮想DOMが差分検知を行い、Propsが変わっていない限り `UserProfileDisplay` は再レンダリングの対象外にできる(`React.memo` を併用すればさらに強固になる)。
—
4. 最後に:設計は「引き算」である
多くのエンジニアがやりがちなのが、最初から「将来の再利用性」を考えて抽象化しすぎてしまうことだ。
僕がいつもチームに言っているのは、「3回同じことを書くまでは抽象化するな」というルールだ。2回までなら、コピペの方がよほどマシだ。なぜなら、中途半端な共通化は、後で「あっちの画面ではこのPropsがいらない」という修正が入った時に、壊滅的な影響を与えるからだ。
Reactの設計において最も大切なのは、「いかに結合度(Coupling)を下げ、凝集度(Cohesion)を高めるか」。
この視点さえあれば、コードは自然と美しくなる。迷ったら、「これは本当に再利用するのか?」「単にファイルを小さくしたいだけではないか?」と自分に問いかけてみてほしい。
現場のコードは生き物だ。完璧を目指すより、変化に強い「柔軟な構造」を作ること。それが、シニアエンジニアとしての唯一の正解だ。

コメント