useReducer
起きたことを渡す
前のレッスンでは、押したその場で「次の状態」を計算していました。useReducer はここを2つに分けます。部品は起きたことだけを伝え、次の状態を決める仕事は1つの関数にまとめます。
その関数を reducer と呼びます。形は決まっています。
TypeScript (JSX)
function qtyReducer(qty: number, action: QtyAction): number {
// いまの状態と、起きたこと。返すのは次の状態
}第1引数がいまの状態、第2引数が起きたこと、戻り値が次の状態です。それ以外のことはしません。通信もしないし、画面も触りません。同じものを渡せば必ず同じものが返る、ただの計算です。
switch で遷移を並べる
switch の case に操作を並べ、それぞれで次の状態を return します。
別の例として、お気に入りの保存と解除を並べてみます。
TypeScript (JSX)
type FavoriteAction = "save" | "clear";
function favoriteReducer(saved: boolean, action: FavoriteAction): boolean {
switch (action) {
case "save":
return true;
case "clear":
return false;
default:
return saved;
}
}状態の決まりが1か所に並びました。カートの数量でも同じように、増やす・下限を守って減らす・初期値に戻すという規則を reducer に集めます。あとから上限を足すときも、直すのはこの関数だけです。
useReducer で繋ぐ
部品側はこう書きます。
TypeScript (JSX)
const [qty, dispatch] = useReducer(qtyReducer, 1);第1引数が reducer、第2引数が初期値です。返ってくるのは、いまの状態と dispatch の組です。useState の [qty, setQty] とよく似た形をしています。
押したときは、次の値ではなく起きたことを送ります。
TypeScript (JSX)
<button onClick={() => dispatch("increase")}>+1</button>dispatch("increase") を読んだ人は「数量を1つ増やす合図を送った」とだけ分かります。いくつになるのかは reducer を見に行けば必ず書いてある。この分担が useReducer の値打ちです。
演習
カートの数量を reducer で動かします。dispatch は用意してあるので、3つの操作で次の数量を決める分岐を書きます。