使い方
1. カウンターを増やす
const [count, dispatch] = React.useReducer(c => c + 1, 0);
-
dispatch()を呼ぶだけでcountが +1。クリックイベントと相性抜群。
2. 表示/非表示を切り替える
const [open, toggle] = React.useReducer(v => !v, false);
-
toggle()がfalse ⇄ trueを交互に反転。モーダルやドロップダウンに便利。
useReducer の役割
「イベント → 結果」のルールを一か所にまとめて状態管理をスッキリさせる React フック。
-
ロジックをまとめやすい
更新ルールが 1 ファイルに集まり迷子にならない。 -
複雑な状態でも安全
オブジェクトや配列の更新処理を一か所に閉じ込められる。 -
テストしやすい
reducer 関数だけを呼び出して動作確認できる。
ロジックをまとめやすいとは?
useState だと「開く」「閉じる」「リセット」など複数の setXXX が点在しがち。
useReducer なら reducer にすべてのケースを書くだけ。どこで何が起きるか一目でわかり、保守がラクになります。
例:Todo リスト
// reducer.js
export function reducer(state, action) {
switch (action.type) {
case "add":
return [...state, action.text]; // 新しいタスクを追加
case "remove":
return state.filter((_, i) => i !== action.i); // 指定番号を除外
default:
return state;
}
}
// App.jsx
import React from "react";
import { reducer } from "./reducer";
export default function App() {
const [todos, dispatch] = React.useReducer(reducer, []);
const addTodo = () => {
const text = prompt("新しいタスク");
if (text) dispatch({ type: "add", text });
};
return (
<div>
<button onClick={addTodo}>追加</button>
<ul>
{todos.map((t, i) => (
<li key={i} onClick={() => dispatch({ type: "remove", i })}>
{t}(クリックで削除)
</li>
))}
</ul>
</div>
);
}
useReducer のベストプラクティス
-
アクション名は動詞+目的語で揃える
例:addTodo,removeTodo,toggleModal— 後で検索しやすくなる。 -
reducer は純粋関数にする
副作用(API 通信など)は書かず、「入力 → 出力」だけにするとバグを防げる。