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

React 中如何在 WebSocket 事件监听器中使用最新的 Context 函数

问题原因
  • 常见错误:没有通过useContext钩子消费Context,直接调用创建Context时的默认对象,自然只能拿到初始的reload函数
  • 闭包陷阱+清理逻辑缺失:就算正确拿到了Context值,你当前的useEffect没有正确清理旧的WebSocket连接和事件监听器,旧的监听器会一直留存,使用它创建时捕获的旧版本reload函数
解决方案

方案1:先修正Context的消费方式,再补全清理逻辑

首先在组件内用useContext拿到最新的Context值:

import { useContext } from 'react'
import GeneralInfoContext from '你的Context文件路径'

// 组件内部优先执行useContext获取最新值
const generalInfo = useContext(GeneralInfoContext)

然后补全useEffect的清理逻辑,每次依赖变化时销毁旧连接、移除旧监听器:

useEffect(() => {
  if (!isSignedIn) return
  // 声明在useEffect内部,每次重新执行都会拿到最新的reload
  function onMessageFunction(message: MessageEvent) {
    const data = JSON.parse(message.data);
    if (data.type === "reload") {
      generalInfo.reload("orders");
    } else {
      console.log(data);
    }
  }

  const socketInstance = new WebSocket("ws://localhost:5000");
  socket.current = socketInstance;

  socketInstance.addEventListener("open", () => {
    console.log("opened websocket connection! ");
  });
  socketInstance.addEventListener("message", onMessageFunction);

  // 清理逻辑:移除监听器+关闭连接
  return () => {
    socketInstance.removeEventListener("message", onMessageFunction);
    socketInstance.close();
    socket.current = undefined;
  };
}, [isSignedIn, generalInfo.reload]);

方案2:用useRef存最新reload,避免频繁重建连接

如果不想每次reload引用变化就重建WebSocket,可以用ref同步最新的reload函数,不需要把reload加入依赖:

const generalInfo = useContext(GeneralInfoContext);
// 用ref存最新的reload
const reloadRef = useRef(generalInfo.reload);
// 每次reload更新时同步到ref
useEffect(() => {
  reloadRef.current = generalInfo.reload;
}, [generalInfo.reload]);

useEffect(() => {
  if (!isSignedIn) return
  function onMessageFunction(message: MessageEvent) {
    const data = JSON.parse(message.data);
    if (data.type === "reload") {
      // 直接读ref的current,永远是最新值
      reloadRef.current("orders");
    } else {
      console.log(data);
    }
  }

  const socketInstance = new WebSocket("ws://localhost:5000");
  socket.current = socketInstance;

  socketInstance.addEventListener("open", () => {
    console.log("opened websocket connection! ");
  });
  socketInstance.addEventListener("message", onMessageFunction);

  return () => {
    socketInstance.removeEventListener("message", onMessageFunction);
    socketInstance.close();
    socket.current = undefined;
  };
}, [isSignedIn]); // 不需要加reload依赖
可选替代方案

如果你的订单同步实时性要求不高(允许3-5秒延迟),可以不用WebSocket,直接用SWR/React Query这类请求库做定时轮询,不需要自己维护长连接的重连、断连、消息监听逻辑,实现起来更简单稳定。

内容的提问来源于stack exchange,提问作者Matus86309

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 17:48:00