はじめに

「とりあえずここで持っとくか」とuseStateを生やしていった結果、1コンポーネントで7つの状態管理
これ、実務ではよくある構造ですが、レビューアー視点では“持ちすぎ構造”を見逃さないようにしたいところです。

この記事では、「状態を持ちすぎているコンポーネント」をレビューでどう見抜き、どう再設計を促すべきかを整理します。

状態を持ちすぎている兆候

以下のようなコードに出会ったら、少し注意して読み込むべきです。

状態が多すぎる例
export function ProfilePage() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [phone, setPhone] = useState('');
  const [errors, setErrors] = useState({});
  const [loading, setLoading] = useState(false);
  const [editable, setEditable] = useState(true);
  const [history, setHistory] = useState([]);
@Reviewer
状態が7つ以上あり、ロジックも混在しています。
グルーピング・構造分割・責務整理を検討しましょう。
return <Form /* ... */ />; }

なぜ「持ちすぎ」は問題になるのか?

  • 認知コストの増加
    状態同士の依存関係が増えると、何が何のための状態か読み解きにくくなります。

  • 責務の分離が難しくなる
    UIとロジックが混在していると、再利用やテストの妨げになります。

  • パフォーマンス悪化の原因にもなる
    状態の1つが変わるだけで、全部再描画される可能性がある。

状態整理の観点(レビュー時に見るべき)

観点 チェックするポイント 提案すべき方向
状態の数 5〜7個以上に増えている 状態をグルーピング or 別Hookへ分離
状態の種類 UI制御, 入力値, 通信管理が混在 責務ごとに切り出し
更新の関連性 ある状態が他を更新トリガにしている reducer構造へ整理
propsとの重複 親から渡されたpropsを再状態化している そのまま使うかmemoで変換

改善パターン

パターン1:状態をまとめる

const [form, setForm] = useState({
  name: '',
  email: '',
  phone: '',
});
const handleChange = (field: keyof typeof form, value: string) =>
  setForm(prev => ({ ...prev, [field]: value }));
  • 状態がまとまっているのでロジックの記述も簡潔
  • useCallbackで安定化しやすい

パターン2:カスタムHookに切り出す

useForm.ts
export function useForm() {
  const [form, setForm] = useState({ name: '', email: '' });
  const [errors, setErrors] = useState({});
  const update = (k, v) => setForm(f => ({ ...f, [k]: v }));
  return { form, errors, update };
}
ProfileForm.tsx
const { form, errors, update } = useForm();

状態とロジックがセットで分離され、コンポーネントは表示に集中できるようになります。

パターン3:reducerでまとめる

状態間の関係が複雑で、1つの状態変更が他にも影響するような場合は、useReducerの出番です。

useProfileReducer.ts
function reducer(state, action) {
  switch (action.type) {
    case 'update':
      return { ...state, [action.key]: action.value };
    case 'reset':
      return initialState;
    default:
      return state;
  }
}

const [state, dispatch] = useReducer(reducer, initialState);
  • テストもしやすく
  • 状態変更の副作用が明示的になりやすい

構造の違いを図示

UML Diagram
UML Diagram

後者の構造は「誰が何を持っているか」が明確になり、レビュー時も読みやすくなります。

コメント例

状態過多の指摘
@Reviewer: 状態が多く、ロジックが混在しているため、読み手にとって構造の意図が伝わりづらくなっています。カスタムHookやグループ化で分離すると可読性が高まります。
コメント改善提案
- const [name, setName] = ...
- const [email, setEmail] = ...
+ const [form, setForm] = useState({ name: '', email: '' })

まとめ

状態が多すぎるコンポーネントは、一見整って見えても保守性が非常に低くなります。

レビューアーの視点では、以下のような問いを常に意識しておくと良いでしょう。

  • 「この状態、本当にここで持つべきか?」
  • 「この状態、まとめられないか?」
  • 「この責務、UIと関係あるか?」

構造的に“持ちすぎ”を見抜く視点を持つことで、コード全体の構成力や読みやすさを引き上げていくことができます。