ReduxにおけるThunksの紹介
前章では、データ交換のためのサーバー、データベース、クライアントの連携を構築しました。
次に必要なのは、私たちの'同期的に'構成されたReduxアプリケーションが、前章の最後のレッスンで作成した非同期クライアントとやり取りし、リクエストを送信して必要なデータをレスポンスとして取得できるようにするための最後の橋渡しです。
前セクションの最初のレッスンから思い出してください。Reduxは非同期ロジックの処理について何も知りません。このために、thunkミドルウェアを使用します。
このミドルウェアは、送信されたアクションを処理し、私たちのthunkコード内でstoreのメソッドdispatchとgetStateを使用できるようにし、またdispatchメソッドが通常のJSオブジェクトだけでなく、関数やプロミスのようなエンティティも扱えるようにするのを助けます。
通常、thunk関数は2つの引数dispatchとgetState(必要に応じて)で呼び出され、この関数の本体内で使用できます。
これを使用して通常のアクションをディスパッチできます。
また、store.dispatchを介してディスパッチすることもできます。
そのような関数の例を以下に示します:
const changeColorThunk = (dispatch, getState) => {
const colorBefore = getState()
console.log(`以前の色: ${colorBefore.color}`)
dispatch(changeColor())
const colorAfter = getState()
console.log(`新しい色: ${colorAfter.color}`)
}
store.dispatch(changeColorThunk)
では、商品に関するアプリケーションを開きましょう。アプリケーション起動時にサーバーから最初に取得する必要があるのは商品リストです。
通常、thunksはスライスファイルに記述されるため、ファイルproductsSlice.jsを開きます。
朗報は、RTKの関数configureStoreが既にこれを行ってくれるため、Redux Thunkのインストールに煩わされる必要がないことです。
したがって、単にファイルのインポートにcreateAsyncThunkを追加します:
import { createSlice, nanoid, createAsyncThunk } from '@reduxjs/toolkit'
また、クライアントもインポートします:
import { client } from '../../api/client'
では、createAsyncThunkを使って、商品を取得するための最初のthunkを作成しましょう。これはinitialStateオブジェクトの宣言直後に行います:
export const fetchProducts = createAsyncThunk()
createAsyncThunkの最初のパラメータは、生成されるアクションのタイプのための文字列を受け取り、2番目のパラメータはpayloadのためのコールバック関数です。この関数は結果としてデータか、エラーのあるプロミスを返します(ファイルclient.jsを参照)。
この関数のコード内で、client.getを呼び出し、サーバーで指定したパスを渡します(server.js内のhttp.getが受け取るパラメータを確認してください):
export const fetchProducts = createAsyncThunk(
'products/fetchProducts',
async () => {
const response = await client.get('/fakeServer/products')
return response.data
}
)
学生に関するアプリケーションを開いてください。
その中で、ファイルstudentsSlice.jsを開きます。
そこに、thunkを作成するための関数createAsyncThunkと、サーバーにAPIリクエストを送信するためのclientをインポートしてください。
initialStateオブジェクトの宣言直後に、createAsyncThunkを使用して学生リストを取得するためのthunkfetchStudentsを作成してください。
これは、server.jsファイルで指定されたアドレス/fakeServer/studentsにGETリクエストを送信し、レッスン資料に示されているようにresponse.dataを返します。
createAsyncThunkの最初のパラメータとして、アクションタイプのための文字列students/fetchStudentsを指定してください。