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

在自定义Hook中访问Redux selector值仅能获取初始值如何解决

问题原因

你遇到的是闭包陷阱问题:

  • 你的useEffect依赖数组为空,只会在组件首次挂载时执行1次,此时它引用的filterData是首次渲染生成的版本,该版本的闭包永久捕获了初始值storedVal = null
  • 后续storedVal更新时,useCallback会生成新的filterData实例,但useEffect没有重新执行,传感器订阅逻辑里依然持有旧版filterData的引用,因此永远拿不到更新后的值

修复方案

方案1:补充useEffect依赖并添加清理逻辑(推荐)

把filterData加入useEffect的依赖数组,同时添加RxJS订阅的清理逻辑,避免重复订阅和内存泄漏:

const storedVal = useSelector(selectors.selectStoredVal);

const filterData = useCallback(
  () => {
    console.log(storedVal);
  },
  [storedVal]
);

useEffect(
  () => {
    const subscription = orientation.pipe(filter(filterData)).subscribe((data) => {
      console.log('Data filtered correctly, new data received here');
    });
    // 组件卸载/依赖更新时清理旧订阅
    return () => subscription.unsubscribe();
  },
  [filterData] // 补充filterData作为依赖
);

每次filterData更新时,useEffect会先执行清理函数取消旧订阅,再用新版filterData创建新订阅,就能始终拿到最新的storedVal。

方案2:用useRef存储最新值(不需要重新订阅)

如果不想频繁销毁重建订阅,可以用useRef持有最新的storedVal,绕开闭包捕获问题:

const storedVal = useSelector(selectors.selectStoredVal);
// 用ref同步最新的storedVal
const storedValRef = useRef(storedVal);
useEffect(() => {
  storedValRef.current = storedVal;
}, [storedVal]);

const filterData = useCallback(
  () => {
    // 直接从ref取最新值,不需要依赖storedVal
    console.log(storedValRef.current);
  },
  [] 
);

useEffect(
  () => {
    const subscription = orientation.pipe(filter(filterData)).subscribe((data) => {
      console.log('Data filtered correctly, new data received here');
    });
    return () => subscription.unsubscribe();
  },
  [filterData]
);

这种方案下filterData只会生成一次,订阅也只会创建一次,性能更好。

内容的提问来源于stack exchange,提问作者mocode10

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 18:06:02