React Native中Redux状态无法在所有函数中更新的问题
解决Redux闭包导致回调中状态不更新的问题
你的核心问题是onSwipe函数被闭包捕获了旧的Redux状态,即使store已经更新,函数内部依然使用首次渲染时的user值。下面给出两种直接可行的解决方案:
方案1:通过getState获取最新Redux状态
直接在回调中从Redux store获取最新状态,彻底摆脱对外部user变量的依赖。需要使用useStore hook获取store实例:
import { useStore } from 'react-redux'; // 组件内部代码 const user = useSelector((state: RootState) => state.user); const dispatch = useDispatch(); const store = useStore(); // 获取store实例 useEffect(() => { console.log("Effect", user.likes); }, [user]); const onSwipe = useCallback((direction: string, uid: string) => { // 每次调用都获取最新的store状态 const currentState = store.getState() as RootState; const currentUser = currentState.user; if (direction === "right") { console.log("Like", currentUser.likes); const newLike = [...currentUser.likes, uid]; void saveLikeFirebase(currentUser.uid ?? "", newLike).then(() => { dispatch(changeLike(uid)); }) } else { void saveDislikeFirebase(currentUser, currentUser.dislikes, uid).then(() => { dispatch(changeDislike(uid)); }) } }, [dispatch]); // 仅依赖稳定的dispatch,无需监听user变化
这种方式不管useCallback是否被缓存,每次调用onSwipe都会拿到最新的user状态,直接解决闭包问题。
方案2:将异步逻辑移至Redux Toolkit的Async Thunk
把Firebase存储和状态更新的逻辑封装到Redux的异步thunk中,利用thunk自带的getState获取最新状态,完全规避组件层的闭包问题:
1. 在slice中定义异步thunk
// userSlice.ts import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import { saveLikeFirebase, saveDislikeFirebase } from '../path/to/firebase'; // 封装点赞逻辑 export const saveLikeAndUpdate = createAsyncThunk( 'user/saveLikeAndUpdate', async (uid: string, { getState }) => { const state = getState() as RootState; const currentUser = state.user; const newLike = [...currentUser.likes, uid]; await saveLikeFirebase(currentUser.uid ?? "", newLike); return uid; // 返回uid用于更新状态 } ); // 封装点踩逻辑 export const saveDislikeAndUpdate = createAsyncThunk( 'user/saveDislikeAndUpdate', async (uid: string, { getState }) => { const state = getState() as RootState; const currentUser = state.user; const newDislikes = [...currentUser.dislikes, uid]; await saveDislikeFirebase(currentUser, newDislikes, uid); return uid; } ); // 原slice添加extraReducers处理异步结果 const userSlice = createSlice({ name: 'user', initialState: {}, // 你的初始状态 reducers: { // 保留原有的reducer逻辑 }, extraReducers: (builder) => { builder .addCase(saveLikeAndUpdate.fulfilled, (state, action) => { state.likes.push(action.payload); }) .addCase(saveDislikeAndUpdate.fulfilled, (state, action) => { state.dislikes.push(action.payload); }); } });
2. 组件中调用thunk
// Component.tsx const user = useSelector((state: RootState) => state.user); const dispatch = useDispatch(); useEffect(() => { console.log("Effect", user.likes); }, [user]); const onSwipe = useCallback((direction: string, uid: string) => { if (direction === "right") { dispatch(saveLikeAndUpdate(uid)); } else { dispatch(saveDislikeAndUpdate(uid)); } }, [dispatch]);
这种方式将业务逻辑统一放到Redux层,组件只负责触发action,代码更简洁,同时彻底解决闭包问题。
为什么之前的尝试无效?
- 改用useState:本质还是组件层状态,同样会遇到闭包问题,还会增加Redux与组件状态同步的复杂度。
- 移除useCallback:如果第三方库在初始化后没有监听
onSwipeprops的变化,组件重新渲染时新的函数不会被第三方库接收,依然使用旧函数。
内容的提问来源于stack exchange,提问作者Alex Di Maria
相关产品推荐
相关产品推荐

