You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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')
  })
}
原因分析
  1. 未返回Promise链:loginAsync是async函数,但内部使用.then/.catch时没有返回这个Promise,导致createAsyncThunk接收到的是一个状态为resolved的Promise(值为undefined),直接触发fulfilled reducer。
  2. 错误处理方式错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 16:05:17