在自定义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
相关产品推荐
相关产品推荐

