React中Stomp订阅回调内myState为空的问题求助
问题原因与解决方案
这是React的闭包陷阱导致的:你的onMessageReceiveEvent函数在组件渲染时创建,会捕获当前渲染周期的myState值。而你的useEffect仅在d1或d2变化时重新执行、创建新的订阅和回调。后续组件因myState更新重新渲染时,旧订阅的回调依然引用初始的空数组myState,所以打印结果为空。
解决方案1:用useRef保存最新状态引用
通过useRef存储最新的myState,它的.current属性可变且不会被闭包锁定,每次状态更新时同步更新ref:
const [myState, setState] = useState([/* 初始数组值 */]); const myStateRef = useRef(myState); // 同步状态到ref,确保ref始终指向最新值 useEffect(() => { myStateRef.current = myState; }, [myState]); const onMessageReceiveEvent = (res) => { console.log(myStateRef.current); // 此处可获取最新状态 }; // 原useEffect逻辑保持不变 useEffect(() => { if (d1 && d2) { const socket = new SockJS(WS_URL, {}, {CheckOrigin: () => false}); stompClient = Stomp.over(socket); stompClient.connect({}, () => { stompClient?.subscribe(`/topic/chat/${d1.id}`, onMessageReceiveEvent); stompClient?.subscribe(`/topic/chat/status/${d1.id}`, onCurrentReplyEvent); }); } return () => { stompClient?.disconnect(); } },[d1,d2]);
解决方案2:用函数式更新获取最新状态(若目标是更新状态)
如果你的需求是在回调里更新myState,直接使用函数式更新即可,React会自动传入最新的状态值,无需依赖当前myState:
const onMessageReceiveEvent = (res) => { // 示例:添加新数据到状态数组 setState(prevState => { console.log(prevState); // 此处为最新状态 return [...prevState, 新数据]; }); };
解决方案3:让回调依赖最新状态(配合useCallback与重新订阅)
用useCallback包裹回调函数,将其加入useEffect的依赖列表,这样每次myState变化时,useEffect会重新执行并创建新订阅(注意先取消旧订阅):
const onMessageReceiveEvent = useCallback((res) => { console.log(myState); }, [myState]); useEffect(() => { if (!d1 || !d2) return; const socket = new SockJS(WS_URL, {}, {CheckOrigin: () => false}); const client = Stomp.over(socket); let subscription1, subscription2; client.connect({}, () => { subscription1 = client.subscribe(`/topic/chat/${d1.id}`, onMessageReceiveEvent); subscription2 = client.subscribe(`/topic/chat/status/${d1.id}`, onCurrentReplyEvent); }); return () => { // 清理旧订阅 subscription1?.unsubscribe(); subscription2?.unsubscribe(); client.disconnect(); } },[d1,d2, onMessageReceiveEvent]);
内容的提问来源于stack exchange,提问作者Gulshan Kumar
相关产品推荐
相关产品推荐

