Redux Toolkit中Firebase登录失败为何进入fulfilled?如何捕获错误?
问题
在Redux Toolkit的Slice中集成Firebase登录功能时,输入错误凭据后,状态先变为pending,随后直接进入success状态,无法捕获Firebase抛出的错误。
相关代码如下:
loginAsync 代码
export const loginAsync = createAsyncThunk('user/login', async (credentials: ILoginCredentials) => { signInWithEmailAndPassword( auth, credentials.email, credentials.password ) .then((userCredential) => { const user = userCredential.user return user }) .catch((error) => { console.log('failed') return isRejectedWithValue(error.message) }) })
Slice 中的 extraReducers 代码
extraReducers: (builder) => { builder.addCase(loginAsync.pending, (state, action) => { console.log('pending') state.loading = 'pending' }) builder.addCase(loginAsync.fulfilled, (state, action) => { state.user = action.payload state.loading = 'succeeded' console.log(state.loading) }) builder.addCase(loginAsync.rejected, (state, action) => { state.loginError = action.error.message state.loading = 'failed' console.log('failed') }) }
原因分析
- 未返回Promise链:
loginAsync是async函数,但内部使用.then/.catch时没有返回这个Promise,导致createAsyncThunk接收到的是一个状态为resolved的Promise(值为undefined),直接触发fulfilled reducer。 - 错误处理方式错误:
rejectWithValue(代码中误写为isRejectedWithValue)需要通过返回的方式告知createAsyncThunk进入rejected状态,而不是return普通值——return普通值会被当作成功的payload处理。
解决方案
修正 loginAsync 代码
改用async/await + try/catch的写法,同时正确使用rejectWithValue传递错误:
export const loginAsync = createAsyncThunk('user/login', async (credentials: ILoginCredentials, { rejectWithValue }) => { try { // 用await等待异步操作完成 const userCredential = await signInWithEmailAndPassword( auth, credentials.email, credentials.password ) // 成功时返回用户信息 return userCredential.user } catch (error) { console.log('failed') // 用rejectWithValue传递错误信息,触发rejected reducer return rejectWithValue(error.message) } })
调整 Slice 的 rejected 处理
使用rejectWithValue后,错误信息会被放在action.payload中,因此可以优化rejected reducer的逻辑:
builder.addCase(loginAsync.rejected, (state, action) => { // 优先取自定义错误信息,兜底用默认error信息 state.loginError = action.payload || action.error?.message || '登录失败' state.loading = 'failed' console.log('failed') })
关键要点
- 确保
async函数返回正确的异步结果或通过rejectWithValue传递错误,让createAsyncThunk能正确识别状态 rejectWithValue需要从thunk的第二个参数中解构获取- 在rejected reducer中,优先读取
action.payload获取自定义错误,避免依赖action.error的结构差异
内容的提问来源于stack exchange,提问作者lams
相关产品推荐
相关产品推荐

