const [state, dispatch] = useReducer(reducer, initialState)
type State = { count: number; status: 'idle' | 'loading' };
type Action =
| { type: 'INCREMENT' }
| { type: 'SET_LOADING'; payload: boolean };
function reducer(state: State, action: Action): State { ... }import { useReducer } from 'react';
// ── 状態の型と初期値 ──────────────────────────────────
type State = { count: number; step: number };
const initialState: State = { count: 0, step: 1 };
// ── アクション(何が起きたかを表す) ─────────────────
type Action =
| { type: 'increment' } // カウントを増やす
| { type: 'decrement' } // カウントを減らす
| { type: 'reset' } // 初期値に戻す
| { type: 'setStep'; step: number }; // ステップを変更
// ── reducer: (現在の状態, アクション) → 新しい状態 ───
// ※ switch-case で各アクションを処理する
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + state.step };
case 'decrement':
return { ...state, count: state.count - state.step };
case 'reset':
return initialState; // 初期値に戻す
case 'setStep':
return { ...state, step: action.step };
default:
return state; // 知らないアクションは無視
}
}
function Counter() {
// dispatch: アクションを送信する関数
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>カウント: {state.count}(ステップ: {state.step})</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>リセット</button>
<select onChange={e => dispatch({ type: 'setStep', step: Number(e.target.value) })}>
<option value={1}>1</option>
<option value={5}>5</option>
<option value={10}>10</option>
</select>
</div>
);
}useState が複数あって連動している場合や、次の状態が複数の前状態に依存する場合は useReducer が整理しやすい。