Reduxにおけるactionオブジェクトのデータ準備
最近、我々はcreateSlice関数がaction.payloadを作成する際に一つの引数を期待するという話をしました。一方ではこれはその使用を簡素化しますが、他方ではactionオブジェクトの中身を準備するために追加の手順を必要とするかもしれません。
商品アプリケーションとその中のファイルNewProductForm.jsxを開きましょう。以下のコード行に注目してください:
dispatch(productAdded({
id: nanoid(), name, desc, price, amount
}))
ここでは、payloadオブジェクトをReactコンポーネント内で直接構築し、それをアクションproductAddedに渡しています。もし、同じアクションを複数のコンポーネントから送信する必要があったり、構築のロジックが複雑になったりしたらどうでしょうか?理想的には、私たちのコンポーネントは、このアクションに対するpayload内のオブジェクトの形状を気にするべきではありません。さらに、コードの常時重複にも満足できません。
これらの問題は、再び私たちの有名なcreateSliceが解決を助けることができます。なぜなら、レデューサーを記述する際に、さまざまなロジックを書いたり、乱数を生成したりできるコールバック関数prepareの使用を可能にするからです。その場合、レデューサーフィールドの値は次のようなオブジェクトとして表すことができます:
{reducer, prepare}
ファイルproductsSlice.jsを開き、レデューサーproductAddedのコードを変更しましょう。このコード部分:
productAdded(state, action) {
state.push(action.payload)
},
これを次のように変更します。ここではreducer関数がstore内のステート更新を担当し、prepareが生成されたidとその他のデータを含むpayloadオブジェクトを返します:
productAdded: {
reducer(state, action) {
state.push(action.payload)
},
prepare(name, desc, price, amount) {
return {
payload: {
id: nanoid(),
name,
desc,
price,
amount,
},
}
},
},
ここでidを生成するため、コンポーネントではなくここで生成します。nanoidをインポートに追加しましょう:
import { createSlice, nanoid } from '@reduxjs/toolkit'
最後に、NewProductForm.jsxに変更を加えます。この行の代わりに:
dispatch(productAdded({
id: nanoid(), name, desc, price, amount
}))
必要なデータを単にカンマ区切りで渡す次の行になります(このファイルではインポートからnanoidを削除することを忘れないでください):
dispatch(productAdded(name, desc, price, amount))
アプリケーションを起動し、新しい商品を作成して、何も壊していないことを確認しましょう。
学生アプリケーションを開いてください。ファイルStudentsSlice.js内で、あなたのレデューサーstudentAddedを、レッスンで示したように{reducer, prepare}の形式のオブジェクトになるよう書き直してください。
レッスンで示したように、ファイルNewStudentForm.jsxに適切な変更を加えてください。アプリケーションを起動し、全てが以前と同じように動作することを確認してください。