useReducerとは
useReducer
は、useState
と同じく値を管理できるフックです。
構文は以下の通りです。
const [state, dispatch] = useReducer(stateを更新する関数, stateの初期値);
// state初期値0で更新関数を実行するとstateの値から+1する例
const [state, dispatch] = useReducer(prev => ++prev, 0);
usetStateとの違い
useState
では更新用関数は、使用時に新しい値をどのように変更するか記述するのに対して、useReducer
では定義時に第一引数に新しい値をどうするか記述します。
// 例 useState
const [state, setState] = useState(0);
<button onClick={() => { setState((prev) => ++prev); }}>
+
</button>
// 例 useReducer
const [state, dispatch] = useReducer(prev => ++prev, 0);
<button onClick={() => { dispatch(); }}>
+
</button>
useState → 利用側が状態の更新の仕方を決定する
useReducer → 状態側で更新の仕方を決定する
上記のような違いから、useReducer
は、大きなアプリケーションを作成する場合や、多数で開発する場合に使用するメリットが多くなってきます。
個人開発ではuseState
だけでも問題ありませんが、他の開発者と協働した場合、useState
では利用者側が更新の仕方を決定するため意図しない使われ方をする場合があります。
useReducerを使ったシンプルなコード例
useReducer
を使って、ボタンクリックに応じてカウントが増減するコード例です。
import { useReducer } from "react";
const Example = () => {
const reducer = (prev, { type }) => {
switch (type) {
case "+":
return ++prev;
case "-":
return --prev;
default:
throw new Error("不明なactionです");
}
};
const [rstate, dispatch] = useReducer(reducer, 0);
const rcountUp = () => {
dispatch({ type: "+" });
};
const rcountDown = () => {
dispatch({ type: "-" });
};
return (
<>
<h3>{rstate}</h3>
<button onClick={rcountUp}>+</button>
<button onClick={rcountDown}>-</button>
</>
);
};
export default Example;
useReducer()
定義時に第一引数に渡している更新用関数reducer
に注目してください。
(prev, { type }) => {
switch (type) {
case "+":
return ++prev;
case "-":
return --prev;
default:
throw new Error("不明なactionです");
}
}
更新用関数では第一引数に前回の値のstate値
が渡されます。今回で言ったらprev
にstate
の値が渡ってきます。
そして第二引数では、更新用関数実行時、つまりdispatch()
実行時の引数が渡ってきます。
今回の例では、{ type }
と、分割代入でtypeプロパティの値を渡しています。
ボタン押下時にdispatch({ type: "+" });
と実行しているので、引数にはオブジェクトが渡ってきて、type
プロパティの値に応じて、switch
させているという流れです。