使用createAsyncThunk调用Firebase的onAuthStateChanged时extraReducers拿不到返回值如何解决
问题修复方案
问题根因
createAsyncThunk的payload值取自你传入的async函数的返回值,你当前的thunk回调没有主动返回任何内容,默认返回undefined,所以fulfilled回调中无法拿到有效值onAuthStateChanged是回调式监听器API,你写在它回调内部的return只会作用于回调本身,不会作为外层thunk函数的返回值被捕获- 你没有将回调式API包装为Promise,async函数不会等待回调执行完毕就会结束执行,最终返回空值
修复代码(单次校验登录状态场景)
将onAuthStateChanged包装为Promise返回,即可让thunk正确拿到返回值:
import { createAsyncThunk, createSlice} from "@reduxjs/toolkit"; import { getAuth, onAuthStateChanged, signOut } from "firebase/auth"; // 注意原type字符串里的拼写错误:checkUSerSignIn 修正为 checkUserSignIn export const checkUserSignIn = createAsyncThunk( "auth/checkUserSignIn", async () => { const auth = getAuth(); // 包装为Promise等待身份状态返回 return new Promise((resolve) => { const unsubscribe = onAuthStateChanged(auth, (user) => { unsubscribe(); // 拿到单次结果后取消监听,避免内存泄漏 resolve(!!user); // 用户存在返回true,否则返回false }); }); } );
你的slice代码不需要做任何修改,修改后fulfilled回调中就能正常获取到布尔类型的action.payload值。
可选优化方案(全局持续监听身份状态场景)
如果你的业务需要实时响应身份状态变化(比如用户在其他端登出后同步更新当前页面状态),更推荐直接在thunk中触发同步reducer更新状态,无需依赖createAsyncThunk的fulfilled回调:
const authSlice = createSlice({ name: "auth", initialState: { auth: { isLoading: false, isAuthenticate: false, user: null, }, }, reducers: { // 新增同步更新身份状态的reducer setAuthState: (state, action) => { state.auth.isLoading = false; state.auth.isAuthenticate = action.payload.isAuthenticate; state.auth.user = action.payload.user; } }, extraReducers: (builder) => { builder .addCase(initAuthListener.pending, (state) => { state.auth.isLoading = true; }) }, }); export const { setAuthState } = authSlice.actions; // 全局初始化调用一次即可持续监听身份变化 export const initAuthListener = createAsyncThunk( "auth/initAuthListener", async (_, { dispatch }) => { const auth = getAuth(); onAuthStateChanged(auth, (user) => { dispatch(setAuthState({ isAuthenticate: !!user, user: user })); }); } );
内容的提问来源于stack exchange,提问作者Lộc Trần Phước
相关产品推荐
相关产品推荐

