[React.js] - パート13: React Hooks - useReducer Hook

Ace Lennox
2025年01月19日読了時間:3分

ReactのuseReducerフックは、useStateの強力な代替手段であり、複雑な状態ロジックを管理するのに役立ちます。このガイドでは、useReducerの構文と用途を分かりやすい例を使って詳しく解説します。


useReducerとは?

useReducerフックは、カスタムロジックを使って状態を管理する方法を提供します。特に次のような場合に有効です:

  1. 複数の値を含む状態管理が必要なとき。

  2. 状態更新が複雑なロジックに依存する場合。

useStateが単純なアップデート関数を使用するのに対し、useReducerでは状態更新を一元化して管理するリデューサー関数を使用します。これにより、コードの可読性とメンテナンス性が向上します。


構文

useReducerフックは、次の2つの引数を受け取ります:

  1. リデューサー関数:ディスパッチされたアクションに基づいて状態変更を決定します。

  2. 初期状態:状態の初期値。単純な値またはオブジェクトとして設定できます。

const [state, dispatch] = useReducer(reducer, initialState);
  • state: 現在の状態値。

  • dispatch: 状態更新をトリガーするための関数。


例1: シンプルなカウンター

まず、useReducerを使ってシンプルなカウンターアプリを作成します:

import { useReducer } from "react";
import ReactDOM from "react-dom/client";

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    case "DECREMENT":
      return { count: state.count - 1 };
    case "RESET":
      return { count: 0 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <h1>カウント: {state.count}</h1>
      <button onClick={() => dispatch({ type: "INCREMENT" })}>増やす</button>
      <button onClick={() => dispatch({ type: "DECREMENT" })}>減らす</button>
      <button onClick={() => dispatch({ type: "RESET" })}>リセット</button>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Counter />);

この例では、状態の複数の遷移(増加、減少、リセット)を単一の関数で管理しています。


例2: ショッピングカート管理

次に、実用的な例としてショッピングカートアプリを作成します:

import { useReducer } from "react";
import ReactDOM from "react-dom/client";

const initialCart = [];

function cartReducer(state, action) {
  switch (action.type) {
    case "ADD_ITEM":
      return [...state, { id: action.id, name: action.name, quantity: 1 }];
    case "REMOVE_ITEM":
      return state.filter((item) => item.id !== action.id);
    case "INCREASE_QUANTITY":
      return state.map((item) =>
        item.id === action.id
          ? { ...item, quantity: item.quantity + 1 }
          : item
      );
    case "DECREASE_QUANTITY":
      return state.map((item) =>
        item.id === action.id && item.quantity > 1
          ? { ...item, quantity: item.quantity - 1 }
          : item
      );
    default:
      return state;
  }
}

function ShoppingCart() {
  const [cart, dispatch] = useReducer(cartReducer, initialCart);

  const addItem = (id, name) => {
    dispatch({ type: "ADD_ITEM", id, name });
  };

  return (
    <div>
      <button onClick={() => addItem(1, "りんご")}>りんごを追加</button>
      <button onClick={() => addItem(2, "バナナ")}>バナナを追加</button>
      <h2>ショッピングカート:</h2>
      {cart.map((item) => (
        <div key={item.id}>
          <p>
            {item.name} (x{item.quantity})
            <button onClick={() => dispatch({ type: "INCREASE_QUANTITY", id: item.id })}>+</button>
            <button onClick={() => dispatch({ type: "DECREASE_QUANTITY", id: item.id })}>-</button>
            <button onClick={() => dispatch({ type: "REMOVE_ITEM", id: item.id })}>削除</button>
          </p>
        </div>
      ))}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<ShoppingCart />);

この例では、複数のアクション(追加、削除、数量の増減)を一元管理するcartReducerを使用しています。


なぜuseReducerを使うのか?

useReducerを使う理由として以下が挙げられます:

  1. ロジックの一元化: 状態の遷移ロジックを1つの関数にまとめることで、メンテナンス性が向上します。

  2. 拡張性: アプリが拡大しても、ロジックを簡単に追加できます。

  3. 予測可能な更新: リデューサーが状態更新を一貫して処理します。


ベストプラクティス

  1. 純粋なリデューサー関数を保つ: APIコールなどの副作用はリデューサーに含めず、useEffectを使用しましょう。

  2. 明確なアクションタイプを使用: アクションタイプをわかりやすい名前にすることで、リデューサーのロジックを理解しやすくなります。

  3. 関連状態をグループ化: 複数の関連する状態をオブジェクトとして管理すると整理しやすくなります。


まとめ

useReducerフックは、複雑な状態遷移を必要とするアプリケーションで非常に役立つツールです。このフックを習得することで、Reactアプリケーションの状態管理をより効率的かつスケーラブルにすることができます。

この記事で紹介した例を試して、useReducerの便利さをぜひ実感してください!


ソースコード

このプロジェクトの完全なソースコードはGitHubで利用可能です。


最近の投稿

Latest Posts


logo

プログラミング、ウェブ開発、モバイルアプリ作成に関する洞察的な記事とチュートリアルを探索します。ReactJS、Next.js、Android、iOS、および最新のコーディングプラクティスについて学びます。実践的な例と、アプリケーションを構築するためのヒントを学びます。すべてのレベルの開発者がスキルを向上させるための理想的な場所です。

SNS

© 2025. All rights reserved