Reduxにおける追加レデューサー

商品アプリケーションを開き、その中のファイル productsSlice.js を開いてみましょう。おそらく、あなたは thunk fetchProducts を別の関数として作成したことに気づいたでしょう?私たちがそうしたのは、createSlice が thunk の定義をサポートしていないからです。では、この場合、スライスの reducer products に、products の外部で定義されたアクションに対応させるにはどうすればよいでしょうか?結局のところ、私たちはまさに thunk fetchProducts が送信するアクションを処理する必要があるのです。

このような場合のために、createSlice には extraReducers というプロパティがあります。これを使うと、このスライスで定義されていないアクションを処理する 追加のレデューサー を追加できます。

では、すべてのレデューサーを持つプロパティ reducers の後に、関数 createSlice の本体にもう1つのメソッド extraReducers を追加しましょう:

products/productsSlice.jsextraReducers() {},

このメソッドには、追加のレデューサーを追加するためのメソッドを持つ builder オブジェクトを渡す必要があります:

products/productsSlice.jsextraReducers(builder) {},

私たちは builder のメソッドの1つ、addCase を使用します。このメソッドは、最初のパラメータに action creator を、2番目のパラメータに reducer を受け取ります。fetchProducts がリクエスト時に送信するアクションの1つは fetchProducts.pending です。これはリクエストが送信されたことを示します。この場合、ステータスを 'in progress' に変更しましょう(以前は 'idle' でした):

products/productsSlice.jsextraReducers(builder) {
  builder.addCase(fetchProducts.pending, (state) => {
    state.status = 'in progress'
  })
},

次に、リクエストが成功した場合に送信されるアクションを処理しましょう。ここでは、ステータスを 'success' に変更するだけでなく、アクションの payload から商品をスライス products に取得します。すべての商品を収集するには、concat メソッドが必要です:

products/productsSlice.jsextraReducers(builder) {
  builder
    .addCase(fetchProducts.pending, (state) => {
      state.status = 'in progress'
    })
    .addCase(fetchProducts.fulfilled, (state, action) => {
      state.status = 'success'
      state.products = state.products.concat(action.payload)
    })
},

リクエストが失敗した場合、ステータスを 'fail' に変更し、エラーメッセージをステートに書き込みます:

products/productsSlice.js.addCase(fetchProducts.rejected, (state, action) => {
  state.status = 'fail'
  state.error = action.error.message
})

今、アプリケーションを起動してメニューで 'Products' をクリックすると、数秒後(サーバーに設定した遅延を覚えていますか?)に商品リストが表示されます。

Redux DevTools でも同様に変更が確認できます。商品はステートにも表示されます('State' タブをクリックして、アクション products/fetchProducts/fulfilled をクリックしてみてください)。そこには新しいステータス 'success' も表示されます。次に、アクション products/fetchProducts/pending をクリックして、'State' タブがどのように変わったか確認してみましょう。

起こり得る唯一の厄介なこと(前のレッスンで話しました)は、データリクエストの重複です。その結果、リストには 8 ではなく、まるで 16 個の商品が表示され、開発者コンソールに重大な警告が表示される可能性があります。この問題については次のレッスンで解決しましょう。

Задание 1

学生用のアプリケーションを開いてください。その中のファイル studentsSlice.js を開きます。関数 createSlice の本体で、プロパティ reducers の後に、プロパティ extraReducers を追加してください。メソッド extraReducers に builder を渡してください。

Задание 2

メソッド builder.addCase を使用して、データリクエスト時に fetchStudents が送信するアクション pending、fulfilled、rejected の処理を追加してください。レッスンで示したように行います。