在 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都是新的,不存在老的状态出来。
这是为什么呢?
-
useEffect 场景:
- 当 tab 的 activeKey 变化触发 useEffect 时,setType 会发起 Redux 状态更新
- Redux 状态更新是异步的,而 React 的 useEffect 依赖项变化会立即触发重新渲染
- 在第一次 getData 调用时,Redux 的 type 可能还未完成更新,导致获取到旧值
- 第二次调用则是更新完成后的新值
-
onClick 场景:
解决方案
方案一:使用 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 的中间件处理流程:
- useEffect 的依赖变化会触发重新渲染,此时 Redux 状态可能处于中间状态5
- Redux-saga 等中间件处理异步操作时会有微任务延迟
- 直接事件处理(如 onClick)会立即触发同步更新流程3
建议优先采用方案四的路由参数同步方案,这既能保持状态一致性,又能解决页面刷新后的状态恢复问题。