つくる - カート完成

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

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

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

材料を持たない action もある

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

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

reducer 側も1行です。

case "CLEAR": return [];

合計は state に持たない

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

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

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 があります。売り切れの商品はカートに入れられないようにします。ボタンそのものを押せなくするのが素直です。

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

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

演習

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

ヒント

App.tsx
App.tsx
プレビュー

できているか

  • 売り切れの追加ボタンが押せない
  • スニーカーを入れると 1 点・4800 円になる
  • 革靴も入れると 2 点・14600 円になる
  • スニーカーの +1 で 3 点・19400 円になる
  • 革靴を削除すると 2 点・9600 円になる
  • -1 を押すと数量が1に戻る
  • カートを空にするで空の表示に戻る