Redux数组状态无法触发useEffect的原因及解决方案
Redux数组状态更新无法触发useEffect的解决方案
问题根源
核心问题是原地修改了Redux状态的引用,导致Redux的浅比较机制认为状态未变化,组件不触发重渲染,useEffect自然也不会执行。
具体问题点:
- 代码中
let _markers = markers;只是复制原数组的引用,而非创建新数组 - 后续循环修改
_markers[m][i]属于原地修改原数组内的对象,Redux状态的引用始终没变 - useSelector默认用浅比较,原数组引用未变时,组件的
markers变量不会更新,useEffect依赖数组也不会触发回调
解决方案:创建新的状态引用
必须确保每次更新状态时返回新的数组/对象引用,让Redux能检测到状态变化。
1. 修改_markers的生成逻辑
不再直接引用原数组,而是创建原数组及元素对象的新引用:
const i = store.getState().lyricIndexState; // 对原数组做浅拷贝,同时为每个元素对象创建新副本 let _markers = markers.map(item => ({ ...item })); let added = false; for (let m = 0; m < _markers.length; m++) { const marker = _markers[m]; if ( marker.start_index === i || marker.end_index === i || (i > marker.start_index && i < marker.end_index) ) { if (type === "add") { marker[i] = `${store.getState().lyricState[i]}:${store.getState().AudioCurrentTimeState}`; } else { marker[i] = -1; } added = true; } }
2. 直接dispatch新数组
去掉先设null的hack操作,直接dispatch新生成的数组:
dispatch({ type: "MarkerReducer/SET", value: _markers, });
3. 验证reducer逻辑
你的reducer本身逻辑没问题,只要action.value是新数组引用,就能触发Redux状态更新:
export const markerReducer = (value = [], action: any) => { switch (action.type) { case "MarkerReducer/SET": return action.value; // 返回新数组引用 default: return value; } };
4. useEffect正常触发
此时useSelector会检测到markerState的引用变化,更新组件的markers变量,进而触发useEffect:
const markers: any = useSelector((state: RootState) => state.markerState); useEffect(() => { // 现在会正常执行回调逻辑 }, [markers]);
关键注意事项
- 永远不要原地修改Redux状态:Redux要求状态不可变,所有更新必须返回新引用
- 数组更新常用方法:
[...原数组]、array.map()、array.filter()等,这些方法都会返回新数组 - 对象更新常用方法:
{...原对象, 新属性: 值}、Object.assign({}, 原对象, 新属性)等
内容的提问来源于stack exchange,提问作者fishbowl1
相关产品推荐
相关产品推荐

