添加WebSocket与Subscription后React Apollo Client请求返回空数据
React连接带WebSocket订阅的GraphQL服务器返回空数据(Apollo Studio正常)
问题概述
给React项目添加WebSocket和GraphQL订阅功能后,所有GraphQL请求都返回空数组/无数据;该问题仅在Node.js服务器新增订阅功能后出现,但Apollo Studio Sandbox中请求可正常返回数据。
可能的问题及修复方案
1. React客户端未配置WebSocket订阅链接
当前你的Apollo Client仅配置了HTTP链接处理查询/突变,但订阅请求需要通过WebSocket发送。需添加拆分链接,根据操作类型自动选择HTTP或WebSocket:
修改React端apollo.js:
import { ApolloClient, InMemoryCache, split } from "@apollo/client"; import { setContext } from "@apollo/client/link/context"; import { createUploadLink } from "apollo-upload-client"; import { getMainDefinition } from '@apollo/client/utilities'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { createClient } from 'graphql-ws'; // 定义存储token的键(确保与localStorage存储的键一致) const TOKEN = 'token'; const ADMINTOKE = 'admintoken'; // HTTP链接:处理查询、突变和文件上传 const uploadLink = createUploadLink({ uri: "http://localhost:8000/graphql" }); // WebSocket链接:处理订阅请求 const wsLink = new GraphQLWsLink(createClient({ url: 'ws://localhost:8000/graphql', connectionParams: { token: localStorage.getItem(TOKEN), admintoken: localStorage.getItem(ADMINTOKE) }, })); // 拆分链接:根据操作类型选择对应传输方式 const splitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, wsLink, uploadLink, ); // 认证链接:添加请求头 const authLink = setContext((_, { headers }) => { return { headers: { ...headers, token: localStorage.getItem(TOKEN), admintoken: localStorage.getItem(ADMINTOKE) } } }); export const client = new ApolloClient({ link: authLink.concat(splitLink), // 使用拆分后的链接 cache: new InMemoryCache(), });
2. 客户端认证token未正确传递
检查TOKEN和ADMINTOKE常量是否定义:如果未声明,localStorage.getItem(TOKEN)会获取undefined对应的存储值,导致请求头的token为空。而Apollo Studio中你手动输入了正确的token,所以能正常返回数据。
在apollo.js顶部添加常量定义即可解决(如上代码所示)。
3. 服务器上下文日志错误
server.js中requestDidStart插件打印的contextValue.token不存在,你的context返回的是LogedInUser和LogedInAdmin,修正日志便于调试:
// 替换server.js中的对应插件 { async requestDidStart({ contextValue }) { console.log('当前登录用户:', contextValue.LogedInUser); console.log('当前登录管理员:', contextValue.LogedInAdmin); }, }
4. 服务器端口日志错误
server.js监听8000端口,但日志输出的是4000,修正后避免混淆:
httpServer.listen(8000, () => { console.log(`🚀 Server ready at http://localhost:8000/graphql`) });
验证步骤
- 重启Node.js服务器和React项目
- 打开浏览器开发者工具→Network标签,查看GraphQL请求的Request Headers,确认
token和admintoken是否正确传递 - 查看服务器控制台日志,确认
LogedInUser是否正确获取到用户信息
内容的提问来源于stack exchange,提问作者sPEER PANSER
相关产品推荐
相关产品推荐

