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

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:如果第三方库在初始化后没有监听onSwipe props的变化,组件重新渲染时新的函数不会被第三方库接收,依然使用旧函数。

内容的提问来源于stack exchange,提问作者Alex Di Maria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:55:30