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

如何在React组件中调用graphql-ws createClient的on事件?

在React组件中处理graphql-ws的连接事件(opened/closed)

要在React组件内调用graphql-ws连接事件(opened/closed)对应的业务逻辑,核心是解决客户端回调与组件上下文隔离的问题。以下是两种可行的实现方案:


方案一:自定义Hook封装客户端,动态传入组件回调

把graphql-ws客户端的初始化逻辑封装到自定义Hook中,允许组件传入事件回调,并确保回调始终能访问最新的组件上下文。

自定义Hook实现

import { useState, useEffect, useRef } from 'react';
import { createClient } from 'graphql-ws';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';

export const useGraphqlWsClient = (onOpened, onClosed) => {
  const clientRef = useRef(null);
  const wsLinkRef = useRef(null);

  // 初始化客户端(仅执行一次)
  useEffect(() => {
    if (!clientRef.current) {
      const client = createClient({
        url: GRAPHQL_WS_ENDPOINT ?? "",
        on: {
          opened: () => onOpened?.(),
          closed: () => onClosed?.(),
        },
      });
      clientRef.current = client;
      wsLinkRef.current = new GraphQLWsLink(client);
    }

    // 组件卸载时关闭客户端连接
    return () => clientRef.current?.dispose();
  }, []);

  // 更新回调函数(适配组件内回调的更新)
  useEffect(() => {
    if (!clientRef.current) return;
    clientRef.current.on.opened = () => onOpened?.();
    clientRef.current.on.closed = () => onClosed?.();
  }, [onOpened, onClosed]);

  return wsLinkRef.current;
};

组件中使用

import { useGraphqlWsClient } from './useGraphqlWsClient';

const MyComponent = () => {
  const handleConnectionOpened = () => {
    // 组件内的业务逻辑,比如调用API
    fetch('/api/connection-status', {
      method: 'POST',
      body: JSON.stringify({ status: 'connected' }),
    });
  };

  const handleConnectionClosed = () => {
    // 组件内的业务逻辑
    fetch('/api/connection-status', {
      method: 'POST',
      body: JSON.stringify({ status: 'disconnected' }),
    });
  };

  // 获取wsLink用于Apollo Client配置
  const wsLink = useGraphqlWsClient(handleConnectionOpened, handleConnectionClosed);

  return <div>组件内容</div>;
};

方案二:React Context共享客户端,组件内订阅事件

如果需要在多个组件中复用graphql-ws客户端,可以将客户端放到Context中,组件通过Context获取客户端后,自行绑定/解绑事件。

第一步:创建Context与Provider

import { createContext, useContext, useState, useEffect } from 'react';
import { createClient } from 'graphql-ws';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';

const GraphqlWsContext = createContext(null);

export const GraphqlWsProvider = ({ children }) => {
  const [client, setClient] = useState(null);
  const [wsLink, setWsLink] = useState(null);

  useEffect(() => {
    const newClient = createClient({
      url: GRAPHQL_WS_ENDPOINT ?? "",
      on: {}, // 留空,由组件自行绑定事件
    });
    const newWsLink = new GraphQLWsLink(newClient);
    setClient(newClient);
    setWsLink(newWsLink);

    return () => newClient.dispose();
  }, []);

  return (
    <GraphqlWsContext.Provider value={{ client, wsLink }}>
      {children}
    </GraphqlWsContext.Provider>
  );
};

export const useGraphqlWs = () => useContext(GraphqlWsContext);

第二步:组件中订阅事件

import { useEffect } from 'react';
import { useGraphqlWs } from './GraphqlWsProvider';

const MyComponent = () => {
  const { client } = useGraphqlWs();

  useEffect(() => {
    if (!client) return;

    // 定义事件处理函数
    const handleOpened = () => {
      console.log('WS连接成功');
      // 组件内业务逻辑
    };
    const handleClosed = () => {
      console.log('WS连接断开');
      // 组件内业务逻辑
    };

    // 绑定事件
    client.on.opened = handleOpened;
    client.on.closed = handleClosed;

    // 组件卸载时解绑事件
    return () => {
      client.on.opened = () => {};
      client.on.closed = () => {};
    };
  }, [client]);

  return <div>组件内容</div>;
};

注意事项

  • 必须在组件卸载时清理事件绑定或关闭客户端,避免内存泄漏
  • 如果回调依赖组件内的状态/Props,要确保回调始终是最新的(方案一中通过useEffect监听回调变化实现)
  • 不要在组件外部直接绑定组件内的回调,否则组件卸载后回调仍可能被触发,导致错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:30:07