Redux useSelector结合事件总线使用时取值异常求助
问题原因与解决方案
核心问题:闭包陷阱
组件首次渲染时,toto的初始值是null,此时创建的test函数会捕获这个null值的闭包。后续toto更新触发组件重新渲染时,虽然会生成新的test函数,但你在**空依赖的useEffect**里完成了事件订阅,订阅的始终是第一次渲染时的旧test函数——它的闭包里永远是初始的null,所以事件触发时打印的永远是旧值。
而监听toto的useEffect因为把toto作为依赖,每次toto更新都会重新执行,拿到的是最新的toto值,所以能正常打印。
解决方案
方案一:用useCallback+动态订阅(推荐)
通过useCallback缓存test函数,确保toto更新时生成新的函数实例,同时在useEffect里监听test的变化,每次更新时取消旧订阅、订阅新函数:
const toto = useSelector(state => state.toto); // 用useCallback包裹,依赖toto,toto更新时生成新的test函数 const test = useCallback(() => { console.log(toto); }, [toto]); useEffect(() => { console.log(toto); }, [toto]); useEffect(() => { // 订阅事件 subscribe('showtoto', test); // 组件卸载或test更新时取消订阅,避免内存泄漏和重复订阅 return () => { unsubscribe('showtoto', test); }; }, [test]); // 依赖test,test更新时重新订阅
方案二:直接从Redux Store获取最新状态
如果不想处理闭包,可以直接在事件回调里从Redux Store获取最新的toto值(需要提前导入你的Redux Store实例):
import store from './path-to-your-redux-store'; const toto = useSelector(state => state.toto); const test = () => { // 直接从store获取最新状态,不受闭包影响 const latestToto = store.getState().toto; console.log(latestToto); } useEffect(()=>{ console.log(toto); }, [toto]); useEffect(()=>{ subscribe('showtoto', test); // 记得添加卸载时的取消订阅逻辑 return () => { unsubscribe('showtoto', test); }; },[])
内容的提问来源于stack exchange,提问作者Crypto Powa
相关产品推荐
相关产品推荐

