React中useEffect内调用回调时变量未定义问题排查
问题:WebSocket回调接收值始终为undefined
场景复现
我在React中实现了一个WebSocketProvider组件,通过外部servConn类建立WebSocket连接,新数据到达时会触发onUpdate方法。Provider代码如下:
function WebSocketProvider({ children, user }) { const ws = useRef(null); const channels = useRef({}); const subscribe = (channel, callback) => { channels.current[channel] = callback; }; const unsubscribe = (channel) => { delete channels.current[channel]; }; useEffect(() => { ws.current = servConn; servConn.namespace = "mobile.0"; servConn._useStorage = false; servConn.init( { name: "mobile.0", // optional - default 'vis.0' connLink: "http://10.0.31.17:8084", // optional URL of the socket.io adapter socketSession: "", // optional - used by authentication }, { onRefresh: function () { window.location.reload(); }, onUpdate: function (id, state) { if (channels.current[id]) { // 此处console.log(state)能正常输出数据 channels.current[id](state); } }, onError: function (err) { //console(_('Cannot execute %s for %s, because of insufficient permissions', err.command, err.arg), _('Insufficient permissions'), 'alert', 600); }, } ); }); return ( <WebSocketContext.Provider value={[subscribe, unsubscribe]}> {children} </WebSocketContext.Provider> ); } export { WebSocketContext, WebSocketProvider };
但在子组件WeatherCard中订阅数据时,回调里的message始终是undefined:
export default function WeatherCard() { const [subscribe, unsubscribe] = useContext(WebSocketContext); useEffect(() => { subscribe("0_userdata.0.pv_current_consumption", ({ message }) => { console.log(message); // 此处输出undefined }); }); return ( <div className="test"> </div> ); }
问题原因
你在子组件的回调里用了解构赋值({ message }),但onUpdate传递的state对象中根本不存在message这个属性,所以解构出来的message自然是undefined。
解决方案
1. 直接接收完整的state参数
如果需要获取全部数据,直接去掉解构,接收state参数即可:
useEffect(() => { subscribe("0_userdata.0.pv_current_consumption", (state) => { console.log(state); // 此处能正常输出完整的state数据 }); }, []);
2. 解构state中实际存在的字段
如果state里有特定业务字段(比如value、data等),解构对应字段即可:
// 假设state结构为 { value: 123, timestamp: Date.now() } useEffect(() => { subscribe("0_userdata.0.pv_current_consumption", ({ value }) => { console.log(value); // 输出对应字段的值 }); }, []);
额外优化:修复useEffect的依赖与内存泄漏
你的useEffect没有设置依赖项,会导致组件每次渲染都重复执行订阅逻辑,建议添加空依赖数组,同时在组件卸载时取消订阅,避免内存泄漏:
useEffect(() => { const channel = "0_userdata.0.pv_current_consumption"; subscribe(channel, (state) => { console.log(state); }); // 组件卸载时取消订阅 return () => { unsubscribe(channel); }; }, [subscribe, unsubscribe]);
内容的提问来源于stack exchange,提问作者Thomas Geulen
相关产品推荐
相关产品推荐

