コース一覧
React状態管理:カスタムフック・Context・Reducer
つくる - カート完成

React状態管理:カスタムフック・Context・Reducer

カスタムフック、フックのルール、Context、useContext、useReducer、Actionのunion型を扱う全21レッスンの状態管理コースです。fleamaの商品・フォーム・テーマ・ユーザー・カート状態を、再利用可能なロジックと予測可能な状態遷移へ整理します。

1
カスタムフック
01. なぜカスタムフックか10分
02. useItemsを作る15分
03. useFormを作る15分
04. フックのルール15分
05. フックに型を付ける15分
06. つくる - フック化完了20分
07. 第4章クイズ15分
2
useContext
01. バケツリレーの限界15分
02. Contextを作る15分
03. useContextで使う15分
04. テーマの全体共有15分
05. ユーザー情報の共有15分
06. つくる - Context整備20分
07. 第5章クイズ15分
3
useReducer
01. setStateの散らかり15分
02. useReducer15分
03. Actionのunion型15分
04. カートreducer15分
05. 使い分け10分
06. つくる - カート完成20分
07. 第6章クイズ15分

つくる - カート完成

第6章のまとめとして作る

新しいことは1つだけです。残りはここまでの組み合わせで、fleama のカートを完成させます。

  • action のユニオン型で、カートにできることを一覧にする
  • reducer に決まりごとを集める
  • dispatch で「起きたこと」だけを送る
  • 合計金額と合計点数を、状態から計算して出す

材料を持たない action もある

新しいのはここです。「カートを空にする」に材料は要りません。その場合は type だけの action を足します。

TypeScript (JSX)

type CartAction = | { type: "ADD"; item: Item } | { type: "REMOVE"; id: string } | { type: "CHANGE_QTY"; id: string; qty: number } | { type: "CLEAR" };

reducer 側も1行です。

TypeScript (JSX)

case "CLEAR": return [];

合計は state に持たない

合計金額を useState で持って、追加のたびに足していく書き方をしたくなります。やめてください。カートの中身と合計という同じことを表す値が2つになり、片方だけ古いという事故が必ず起きます。

合計はカートから毎回計算します。

TypeScript (JSX)

const count = cart.reduce((sum, line) => sum + line.qty, 0); const total = cart.reduce((sum, line) => sum + line.item.price * line.qty, 0);

計算し直すのが無駄に見えても、数十行の配列なら人の目には一瞬です。状態は1つ、残りはそこから作るが原則です。

売り切れは入れられない

fleama の商品には status があります。売り切れの商品はカートに入れられないようにします。ボタンそのものを押せなくするのが素直です。

TypeScript (JSX)

<button disabled={item.status === "sold"}>カートに入れる</button>

reducer 側で弾く手もありますが、押せるのに何も起きないボタンは、使う人には壊れて見えます。できないことは、できない見た目にするほうが親切です。

演習

カートを完成させます。追加、数量変更、削除、全消し、合計の表示までを通します。

ヒント

行のクラスは className={"cart-line line-" + line.item.id} の形で作ります

-1 ボタンも +1 ボタンも同じ CHANGE_QTY です。qty に line.qty - 1 と line.qty + 1 を渡し分けます

合計点数は cart.reduce((sum, line) => sum + line.qty, 0) です

売り切れは disabled={item.status === "sold"} で押せなくします

App.tsx
プレビュー

できているか

  • 売り切れの追加ボタンが押せない
  • スニーカーを入れると 1 点・4800 円になる
  • 革靴も入れると 2 点・14600 円になる
  • スニーカーの +1 で 3 点・19400 円になる
  • 革靴を削除すると 2 点・9600 円になる
  • -1 を押すと数量が1に戻る
  • カートを空にするで空の表示に戻る
  • CLEAR を型に足している
  • カートを useReducer で持っている
  • any で逃げていない
エディタを読み込んでいます