在事件监听器中访问Redux state无法获取最新值的替代方案咨询
问题根因
你遇到的是典型的闭包陷阱问题:由于useEffect依赖数组为空,回调函数只会在组件首次渲染时执行一次,内部捕获的subjects props永远是首次渲染时的快照,后续Redux更新props后,监听器里读的还是旧值,自然拿不到最新的subjects.users。另外你直接subjects.users.push()的写法不符合Redux规范,Redux要求state不可变,直接修改原state不会触发视图更新。
替代方案(无需重新注册事件监听器)
方案1:用useRef存储最新的props与更新能力
利用ref的可变特性同步最新的props,监听器内读取ref的current值即可拿到最新状态,完全不需要重建事件连接:
import { useRef, useEffect } from 'react' // 引入你定义的更新users数组的action,示例名为addUser import { addUser } from 'xxx/subjectsAction' const HomeScreen = ({ route, navigation, subjects, addUser}) => { // 定义ref存储最新的subjects和更新方法 const latestSubjectsRef = useRef(subjects) const addUserRef = useRef(addUser) // 每次组件渲染更新ref的值,保证永远同步最新状态 latestSubjectsRef.current = subjects addUserRef.current = addUser useEffect(() => { eventSource = new RNEventSource( environment.server_url + '/events?loginProvider=google', { headers: { 'authorization': `Bearer ${subjects.userToken}` } } ); eventSource.addEventListener('message', (event) => { if (!event.data) return; // 从ref读取最新的users console.log(latestSubjectsRef.current.users) // 通过dispatch更新Redux,不要直接修改原state addUserRef.current(event.data) }); // 组件卸载时清理连接,避免内存泄漏 return () => { eventSource.close() } },[]); } // mapDispatchToProps中新增addUser绑定 const mapDispatchToProps = dispatch => ( bindActionCreators({ logout, setUserId, addUser }, dispatch) );
方案2:直接读取Redux store的最新状态
直接引入项目中初始化好的Redux store实例,调用getState()直接获取全局最新状态,完全不受闭包影响:
// 引入你项目的store实例,通常在store.js文件中导出 import store from 'xxx/store' import { addUser } from 'xxx/subjectsAction' const HomeScreen = ({ route, navigation, subjects}) => { useEffect(() => { eventSource = new RNEventSource( environment.server_url + '/events?loginProvider=google', { headers: { 'authorization': `Bearer ${subjects.userToken}` } } ); eventSource.addEventListener('message', (event) => { if (!event.data) return; // 直接从store拿最新的users数组 console.log(store.getState().subjects.users) // 直接通过store dispatch更新state store.dispatch(addUser(event.data)) }); return () => { eventSource.close() } },[]); }
补充说明:如果你的
userToken存在过期/更新的场景,需要把userToken加入useEffect依赖数组,token变化时要关闭旧连接重新建立连接,避免使用过期token请求接口。
内容的提问来源于stack exchange,提问作者javapedia.net
相关产品推荐
相关产品推荐

