LoginSignup
5
1

More than 1 year has passed since last update.

createAsyncThunkってなに??

Posted at

モチベーション

Redux Toolkitを使っている中で良く見かけるこいつが何者かよく理解しないまま何となくで使ってしまっていたので、自分の知識の整理も含めてアウトプットすることにしました

createAsyncThunkってなに?

一言でまとめると、「非同期処理の実行状況に応じたActionCreatorを生成する関数」
Promiseの状況(pending, fulfilled, reject)に応じたActionCreatorを生成してくれる

createAsyncThunkの使い方

  • どんな値を引数に渡すのか?

    • 第一引数(typePrefix)
      • ActionTypeのprefixとして利用される文字列
      • 型: string
    • 第二引数(payloadCreator)
      • Promiseを返す非同期処理の関数(async関数)
      • 型: AsyncThunkPayloadCreator<Returned, ThunkArg, ThunkApiConfig>
    • 第三引数(options)
      • Thunk API
      • ここはoptional
      • 型: AsyncThunkOptions<ThunkArg, ThunkApiConfig>
  • 型定義

    • createAsyncTunk<Returned, ThunkArg = void, ThunkApiConfig extends AsyncThunkConfig = {}>

型定義ややこしい、、

Returned

Genericで定義しているReturnedは、第二引数に渡しているpayloadCreatorに渡されている
中身を覗いてみると、

type AsyncThunkPayloadCreator<
  Returned,
  ThunkArg = void,
  ThunkApiConfig extends AsyncThunkConfig = {}
> = (arg: ThunkArg, thunkAPI: GetThunkAPI<ThunkApiConfig>)
=> AsyncThunkPayloadCreatorReturnValue<Returned, ThunkApiConfig>

ReturnedはさらにAsyncThunkPayloadCreatorReturnValueに渡っている

type AsyncThunkPayloadCreatorReturnValue<
  Returned,
  ThunkApiConfig extends AsyncThunkConfig
> = Promise<
    Returned |
    RejectWithValue<GetRejectValue<ThunkApiConfig>>> |
    Returned |
    RejectWithValue<GetRejectValue<ThunkApiConfig>
  >;

ReturnedはPromoseの中に入っている
つまり、Returnedは、AsyncThunkPayloadCreatorが返しているAsyncThunkPayloadCreatorReturnValueの型になっている
AsyncThunkPayloadCreatorはcreateAsyncThunkの第2引数
ReturnedcreateAsyncThunkの第2引数の関数の返り値になっているので、fetchしてくるデータの返り値の型を定義してあげれば良い

ThunkArg

こいつもAsyncThunkPayloadCreatorに渡されている
AsyncThunkPayloadCreatorを再度覗くと、第一引数に渡されていることがわかる

type AsyncThunkPayloadCreator<
  Returned,
  ThunkArg = void,
  ThunkApiConfig extends AsyncThunkConfig = {}
> = (arg: ThunkArg, thunkAPI: GetThunkAPI<ThunkApiConfig>)
=> AsyncThunkPayloadCreatorReturnValue<Returned, ThunkApiConfig>

createAsyncThunkの第二引数の第一引数になっている(ややこしい、、)

ThunkApiConfig

Redux ToolkitのThunk APIの型をまとめたもの
AsyncThunkConfigを継承しているので、AsyncThunkConfigを見る

type AsyncThunkConfig = {
    state?: unknown;
    dispatch?: Dispatch;
    extra?: unknown;
    rejectValue?: unknown;
    serializedErrorType?: unknown;
};

どこで使われているかを見ると、こいつもAsyncThunkPayloadCreatorに渡されている
もう一つ深く追っていくと、AsyncThunkPayloadCreatorの第二引数として渡されている
つまり、createAsyncThunkの第二引数の第二引数になっている(ややこしい、、)

実際にどう使うか?

冒頭でも述べているように、createAsyncThunkはActionCreatorを作成するので、createAsyncThunkを使った関数で作られるオブジェクトには、pending,fulfilled,rejectが含まれる

const hoge = createAsyncThunk(省略)

// ↓のように参照できるようになる
hoge.pending
hoge.fulfilled
hoge.reject

実際に使ってみる

action.ts
interface Request {
  name: string;
  age: number;
}

const hoge = createAsyncTunk<{}, Request, AsyncThunkConfig>(
  'type/prefix',
  async (request: Request, thunkApi) => {
    try {
      const res = await axios.get('api/path')
    } catch(error) {
      return thunkApi.rejectWithValue({ message: error.response.data.errors.join('\n') });
    }
)
slice.ts
const slice = createSlice({
  name: 'hoge',
  initialState: initState,
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(hoge.pending, (state) => {
        // 更新させたいstate書く
        // fulfilledとrejectedには、action.payloadに非同期処理の結果の値を入れることができる
        state.name = action.payload.name
        state.submitting = true
    });
    builder.addCase(hoge.fulfilled, (state) => {
        // 更新させたいstate書く
        state.submitting = false
    });
    builder.addCase(hoge.rejected, (state, action) => {
      if (action.payload) {
        state.errorMessage = action.payload.message;
      }
      state.isSubmitting = false;
    });
  },
});

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1