🍒

useReducer(): 基本操作と実装例

2024/07/21に公開

React v16.8.0 以降で導入された useReducer は、複雑な状態管理に適した React のフック。現在の状態とアクションを受け取り、新しい状態を返すリデューサー関数で状態を管理する。useReducer を使用することで、複数の状態遷移を一つの関数内に集約し、状態管理のロジックを明確に保つことができる。

CounterReducer.js
// 1. 状態の初期値を設定する
const initialState = { count: 0 };

// 2. 現在の状態とアクションを受け取り、新しい状態を返すリデューサー関数を作成する
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

export { initialState, reducer };

イベントハンドラーで dispatch を呼び出す場合

() => dispatch({ type: 'INCREMENT' }) のように関数でラップする。

MyComponent.jsx
import React, { useReducer } from 'react';
import { reducer, initialState } from './CounterReducer';

const MyComponent = () => {
  // 3. useReducer フックを使用する
  // 第一引数には、リデューサー関数を指定する
  // 第二引数には、状態の初期値を指定する
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      {/* 関数にして渡す */}
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
};

export default MyComponent;

関数内で dispatch を呼び出す場合

直接呼び出す。

MyComponent.jsx
import React, { useReducer } from 'react';
import { reducer, initialState } from './CounterReducer';

const MyComponent = () => {
  // 3. useReducer フックを使用する
  // 第一引数には、リデューサー関数を指定する
  // 第二引数には、状態の初期値を指定する
  const [state, dispatch] = useReducer(reducer, initialState);

  // 関数内で dispatch を直接呼び出す
  const handleIncrement = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const handleDecrement = () => {
    dispatch({ type: 'DECREMENT' });
  };

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={handleIncrement}>Increment</button>
      <button onClick={handleDecrement}>Decrement</button>
    </div>
  );
};

export default MyComponent;

Discussion