PubSub订阅回调无法获取更新后的Redux状态问题求助
问题原因
你的核心问题是PubSub订阅了旧的回调函数闭包:
- 初始渲染时,
checkIfAuthenticated捕获了isloggedIn=false的状态,并通过pubsub.subscribe注册到事件中。 - 用户登录后
isloggedIn变为true,useCallback生成了新的checkIfAuthenticated函数,useEffect也执行了新的订阅,但旧的订阅没有被取消。 - 第二次点击时,PubSub会触发所有已注册的回调,包括仍持有
isloggedIn=false闭包值的旧回调,因此你会看到错误的状态。
解决方案
步骤1:添加订阅清理逻辑
必须在组件卸载或依赖变化时取消旧订阅,避免旧回调残留:
const CompA = () => { // 假设你通过useSelector获取Redux状态 const isloggedIn = useSelector(state => state.auth.isLoggedIn); // 假设openLoginModal是Redux dispatch方法 const openLoginModal = useDispatch(openLoginModalAction); const checkIfAuthenticated = useCallback(() => { if (!isloggedIn) { openLoginModal(); } else { redirectToAccountDashboard(); } }, [openLoginModal, isloggedIn]); useEffect(() => { // 订阅时保存取消订阅的函数 const unsubscribe = pubsub.subscribe('xyz', checkIfAuthenticated); // 清理函数:取消旧订阅 return () => unsubscribe(); }, [checkIfAuthenticated]); }
步骤2:优化回调以始终获取最新状态(可选)
如果不想每次isloggedIn变化都重新订阅,可以用useRef跟踪最新状态,让回调直接读取最新值:
const CompA = () => { const isloggedIn = useSelector(state => state.auth.isLoggedIn); const openLoginModal = useDispatch(openLoginModalAction); // 用ref保存最新的isloggedIn值 const isloggedInRef = useRef(isloggedIn); useEffect(() => { isloggedInRef.current = isloggedIn; }, [isloggedIn]); // 回调不再依赖isloggedIn,直接读取ref的最新值 const checkIfAuthenticated = useCallback(() => { if (!isloggedInRef.current) { openLoginModal(); } else { redirectToAccountDashboard(); } }, [openLoginModal]); useEffect(() => { const unsubscribe = pubsub.subscribe('xyz', checkIfAuthenticated); return () => unsubscribe(); }, [checkIfAuthenticated]); }
关键说明
- 必须清理订阅是核心,否则旧的闭包回调会一直占用内存并触发错误逻辑。
- 第二种方案通过
useRef避免了频繁重新订阅,适合状态变化频繁的场景,回调始终能拿到最新的Redux状态。
内容的提问来源于stack exchange,提问作者Babitha
相关产品推荐
相关产品推荐

