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

React Apollo useSubscription钩子直接调用无响应,赋值变量则正常

Apollo GraphQL订阅客户端无法触发onData回调的问题

服务器端订阅功能正常,但客户端调用useSubscription时,直接调用无日志输出:

useSubscription(BOOK_ADDED, {
    onData: ({ data }) => {
      console.log(data)
    }
  })

但将调用结果赋值给变量后,onData能正常打印数据:

const value = useSubscription(BOOK_ADDED, {
  onData: ({ data }) => {
      console.log(data)
    }
  })
 console.log(value)

相关配置及代码

index.js(Apollo配置)

import ReactDOM from 'react-dom'
import App from './App'

import {
  ApolloClient,
  ApolloProvider,
  HttpLink,
  InMemoryCache,
  split,
} from '@apollo/client'

import { setContext } from '@apollo/client/link/context'

import { getMainDefinition } from '@apollo/client/utilities'
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
import { createClient } from 'graphql-ws'
import Assess from './Asses'

const authLink = setContext((_, { headers }) => {
  const token = localStorage.getItem('library-user-token')
  return {
    headers: {
      ...headers,
      authorization: token ? `bearer ${token}` : null,
    },
  }
})

const httpLink = new HttpLink({ uri: 'http://localhost:4002' })

const wsLink = new GraphQLWsLink(
  createClient({
    url: 'ws://localhost:4002',
  })
)

const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query)
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    )
  },
  wsLink,
  authLink.concat(httpLink)
)

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: splitLink,
})

ReactDOM.render(
  <ApolloProvider client={client}>
    <Assess />
  </ApolloProvider>,
  document.getElementById('root')
)

App.js

//App.js
import { useSubscription, useQuery } from "@apollo/client";
import { ALL_BOOKS, BOOK_ADDED } from "./queries";

const App = () => {
  console.log(BOOK_ADDED);
  const result = useQuery(ALL_BOOKS);
  useSubscription(BOOK_ADDED, {
    onData: ({ data }) => {
      console.log(data);
    },
  });

  console.log(result)

  if(result.loading){
    return null
  }
  return (
    <div>
      {result?.data?.allBooks.map((r) => (
        <li key={r.id}>{r.title}</li>
      ))}
    </div>
  );
};

export default App

查询及片段

const BOOK_DETAILS = gql`
fragment BookDetails on Books {
      title
      author {
        name
      }
      published
      genres
      id
}
  `;

export const BOOK_ADDED = gql`
  subscription {
    bookAdded {
      ...BookDetails
    }
  }
  ${BOOK_DETAILS}
`;

问题原因及解决方案

核心原因

这个现象是React Hooks的执行机制导致的:当你不接收useSubscription的返回值时,React或Apollo Client的内部优化逻辑可能会跳过订阅的完整初始化流程,导致onData回调没有被正确注册。

快速解决

只需接收useSubscription的返回值即可,哪怕不需要用到该值:

// 接收返回值,无需额外操作
const _ = useSubscription(BOOK_ADDED, {
  onData: ({ data }) => {
    console.log(data);
  },
});

额外检查点

  1. 组件挂载验证:确认<App />确实被<Assess />组件渲染,若App未挂载,订阅不会生效。
  2. WebSocket连接状态:在浏览器开发者工具的Network标签下,检查WS连接是否成功建立,是否收到服务器推送的数据。
  3. WebSocket权限配置:你的authLink仅处理了HTTP请求的权限头,WebSocket连接需要单独配置认证信息,否则服务器可能拒绝订阅请求:
const wsLink = new GraphQLWsLink(
  createClient({
    url: 'ws://localhost:4002',
    connectionParams: () => {
      const token = localStorage.getItem('library-user-token');
      return {
        authorization: token ? `bearer ${token}` : null,
      };
    },
  })
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:25:16