ReactJS+Firestore消息应用:快照返回数组至Reducer时出现undefined
问题原因
你的代码存在两个核心问题,导致action.payload返回undefined:
onSnapshot回调函数内部的return friend无法将值传递到外层async函数,而外层async函数本身没有任何返回值,因此Thunk的最终返回结果为undefined。onSnapshot是实时监听方法,会在数据变化时多次触发回调,但createAsyncThunk是为单次异步任务设计的,两者场景不匹配。
解决方案
根据你的业务需求选择对应方案:
方案1:仅一次性获取用户数据(无需实时更新)
如果不需要监听数据变化,改用getDocs(它返回Promise,可被async/await处理):
export const getFriends = createAsyncThunk( "friends/getFriends", async () => { try { const querySnapshot = await getDocs(collection(db, "users")); const friend = []; querySnapshot.forEach((doc) => { friend.push(doc.data()); }); return friend; } catch (err) { console.log(err); throw err; // 抛出错误让rejected状态捕获 } } );
方案2:需要实时监听用户数据变化
这种场景下createAsyncThunk不适用,建议在组件中直接订阅onSnapshot,并在回调里dispatch普通action更新状态:
1. 定义普通action
export const setFriends = (friends) => ({ type: "friends/setFriends", payload: friends });
2. 在reducer中处理该action
extraReducers: (builder) => { builder // 保留原有单次请求的状态处理(如果需要) .addCase(getFriends.pending, (state) => { state.isLoading = true; }) .addCase(getFriends.fulfilled, (state, action) => { state.isLoading = false; state.friend = action.payload; }) .addCase(getFriends.rejected, (state) => { state.isLoading = false; }) // 添加实时更新的处理逻辑 .addCase(setFriends, (state, action) => { state.friend = action.payload; }); },
3. 在组件中订阅监听
import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { setFriends } from './your-slice-file'; import { collection, onSnapshot } from 'firebase/firestore'; import { db } from './your-firebase-config'; function FriendsComponent() { const dispatch = useDispatch(); useEffect(() => { // 订阅数据变化 const unsubscribe = onSnapshot(collection(db, "users"), (querySnapshot) => { const friend = []; querySnapshot.forEach((doc) => { friend.push(doc.data()); }); dispatch(setFriends(friend)); }); // 组件卸载时取消订阅,避免内存泄漏 return unsubscribe; }, [dispatch]); // ...组件其他渲染逻辑 }
内容的提问来源于stack exchange,提问作者Phú Lệ Nam
相关产品推荐
相关产品推荐

