背景
認証の非同期処理をthunkを使って、サインインが完了したらreduxの値を更新したい。
redux toolkitのcreateAsyncThunkを使う。
createAsyncThunkでrejectWithValueを使った時のpayloadの型がanyになる。
rejectWithValueを使った時のpayloadの型がanyになる
react.js
export const signInThunk = createAsyncThunk(
'auth/signIn',
async (signInArgs: SignInArgs, { rejectWithValue }) => {
try {
const result = await signInFirebaseWithEmailAndPassword({ ...signInArgs });
return { loading: false, error: [], identity: result.identity, statusCode:result.statusCode };
} catch () {
return rejectWithValue({
statusCode: result.statusCode,
});
}
},
);
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {},
extraReducers: (builder) => {
// auth/signIn
builder.addCase(signInWithEmailAndPasswordThunk.fulfilled, (_, action) => ({
...action.payload,
}));
builder.addCase(signInWithEmailAndPasswordThunk.pending, (state) => {
state.loading = true;
});
builder.addCase(signInWithEmailAndPasswordThunk.rejected, (state, action) => {
state.loading = false;
state.error = ['Auth error'];
state.statusCode = action.payload?.statusCode;
});
},
});
解決策
createAsyncThunk<T>
のTの型を定義する。これだけだけど、型の順番に注意が必要。以下の順番になっている。
- 成功した時の戻り値の型
- 引数の型
- rejectWithValueで渡す型
react.js
export const signInThunk = createAsyncThunk<
AuthState, // 成功した時の戻り値の型
SignInArgs, // 引数の型
{ rejectValue: Pick<AuthState, 'statusCode'> } // rejectWithValueで渡す型
>(
'auth/signIn',
async (signInArgs: SignInArgs, { rejectWithValue }) => {
try {
const result = await signInFirebaseWithEmailAndPassword({ ...signInArgs });
return { loading: false, error: [], identity: result.identity, statusCode:200 };
} catch () {
return rejectWithValue({
statusCode: result.statusCode,
});
}
},
);
終わり
redux toolkitは知らないことがまだまだいっぱい。.