记录:非常典型的一个redux问题

在 ApproveCenterList 组件里面,当 tab 的 activeKey 发生变化,我在 useEffect 里面调用 setType 去修改 redux 里面的 type 状态,当type发生变化以后,会去调用redux 的异步方法 getData,然后我就发现在 getData里面,执行console.log(type, 9888); 此时的type会调用2次,第一次的type是老的,第二次是新的,导致最后页面出现异常。

但是在 ApproveCenterList 组件里面,我直接点击按钮,在onClick里面调用setType,去修改 redux 里面的 type 状态,当 type 发生变化以后,会去调用redux 的异步方法 getData,然后我就发现在 getData里面,执行console.log(type, 9888); 此时的type页也会调用2次,第一次和第二次的type都是新的,不存在老的状态出来。

这是为什么呢?

  1. useEffect 场景‌:

    • 当 tab 的 activeKey 变化触发 useEffect 时,setType 会发起 Redux 状态更新
    • Redux 状态更新是异步的,而 React 的 useEffect 依赖项变化会立即触发重新渲染
    • 在第一次 getData 调用时,Redux 的 type 可能还未完成更新,导致获取到旧值
    • 第二次调用则是更新完成后的新值
  2. onClick 场景‌:

    • 直接点击按钮时,setType 同步触发,Redux 会立即处理状态更新
    • 由于setTypegetData 几乎在同一事件循环中执行,是同步操作,getData 两次调用都能获取到最新值

解决方案

方案一:使用 useLayoutEffect

scss 复制代码
jsxCopy Code
useLayoutEffect(() => {
  setType(newType);
}, [activeKey]);

这会确保在 DOM 更新前同步执行状态更新5。

方案二:在 getData 中添加延迟

javascript 复制代码
jsxCopy Code
const getData = () => {
  .....
  //yield delay(10);
  yield new Promise(resolve => setTimeout(resolve, 0));
  //延迟以后
  const currentType = store.getState().type;
  console.log(currentType, 9888);
  ....
  // 后续操作
}

根本原因

这种现象源于 React 的批量更新机制和 Redux 的中间件处理流程:

  1. useEffect 的依赖变化会触发重新渲染,此时 Redux 状态可能处于中间状态5
  2. Redux-saga 等中间件处理异步操作时会有微任务延迟
  3. 直接事件处理(如 onClick)会立即触发同步更新流程3

建议优先采用方案四的路由参数同步方案,这既能保持状态一致性,又能解决页面刷新后的状态恢复问题。

相关推荐
于慨1 天前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz1 天前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶1 天前
前端交互规范(Web 端)
前端
CHU7290351 天前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing1 天前
Page-agent MCP结构
前端·人工智能
王霸天1 天前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航1 天前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界1 天前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript
PieroPc1 天前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi
悟空瞎说1 天前
深入 Vue3 响应式:为什么有的要加.value,有的不用?从设计到源码彻底讲透
前端·vue.js