You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:22:44