组件中无法捕获createAsyncThunk抛出的错误如何解决
以下是编写的登录thunk代码,预期传入错误登录凭证时thunk执行失败:
export const login = createAsyncThunk( "Auth/login", async ({ email, password }: LoginI, { rejectWithValue }) => { try { const user = await api.post( "auth/login", { email, password, }, { withCredentials: true } ); if (user.data.check) { return { loggedState: true, user: user.data.user }; } else { setAxiosToken(user.data.token); saveToken(user.data.getToken); return user.data; } } catch (error: any) { console.log(error); // handleError(error, rejectWithValue); rejectWithValue("Invalid email or password"); } } );
下方是组件中派发该thunk的处理函数,实际测试时传入错误凭证确实会触发thunk内部的catch块,但组件catch块中的console.log(error);语句会在控制台抛出TypeError: payload is undefined错误:
async function handleButtonClick() { try { setCurrentStatus(status.loading); const res = await dispatch( login({ email, password: password.value }) ).unwrap(); console.log(res); if (res.loggedState) { setCurrentStatus(status.askConfirmation); setRequestEmail(res.user.email); } // if (!res.loggedState) navigate("/"); } catch (error: any) { console.log(error); setCurrentStatus(status.failed); setRequestError(error); } }
rejectWithValue是Redux Toolkit提供的工具方法,调用后会返回一个携带自定义错误信息的rejected action对象,必须把这个对象作为异步函数的返回值返回,thunk才能正确识别自定义错误内容。
当前代码在catch块中只调用了rejectWithValue("Invalid email or password"),没有加return关键字,异步函数执行到catch块末尾没有拿到明确返回值,默认返回undefined,最终thunk的rejected状态payload为undefined,.unwrap()抛出错误时就会出现payload不存在的类型错误。
只需要在thunk的catch块中,给rejectWithValue调用前加上return即可:
catch (error: any) { console.log(error); // handleError(error, rejectWithValue); return rejectWithValue("Invalid email or password"); }
修改后,错误凭证场景下thunk会正确返回设置的"Invalid email or password"作为错误载荷,组件的catch块就能正常捕获到自定义错误信息,不会再报payload undefined的问题。
补充:使用
createAsyncThunk时,只要是调用rejectWithValue返回自定义错误,都必须加return,否则都会出现payload为undefined的问题。
内容的提问来源于stack exchange,提问作者Susant Patel

