Next.js 13集成Apollo Client报错:TypeError读取watchQuery失败
问题原因及解决方法
核心问题
你的client.js中初始化client变量时错误地赋值为ApolloClient构造函数,而非undefined:
let client = ApolloClient; // 错误:赋值了构造函数,不是实例
这导致getClient()第一次执行时,!client判断为false(构造函数本身是存在的函数,并非undefined),直接返回构造函数而非ApolloClient实例。而useQuery需要的是客户端实例,构造函数没有watchQuery方法,因此触发报错。
修复步骤
1. 修正client初始化与getClient逻辑
修改client.js,将初始client设为undefined,确保首次调用能正确创建实例:
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client"; let client; // 初始化为undefined export const getClient = () => { // 仅在无实例或服务端环境时创建新客户端 if (!client || typeof window === "undefined") { client = new ApolloClient({ link: new HttpLink({ uri: "https://main--time-pav6zq.apollographos.net/graphql", }), cache: new InMemoryCache(), }); } return client; };
2. 推荐:使用ApolloProvider统一管理客户端
在App Router中,更规范的做法是用ApolloProvider包裹客户端组件,避免每次调用useQuery手动传client:
- 创建
app/providers.js(客户端组件):
"use client"; import { ApolloProvider } from "@apollo/client"; import { getClient } from "./client"; export default function ApolloProviders({ children }) { const client = getClient(); return <ApolloProvider client={client}>{children}</ApolloProvider>; }
- 修改
app/layout.js,引入并使用该Provider:
import ApolloProviders from "./providers"; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <ApolloProviders>{children}</ApolloProviders> </body> </html> ); }
- 之后
page.js中无需手动传client,直接使用useQuery即可:
"use client"; import { gql, useQuery } from "@apollo/client"; const query = gql` query Now { now(id: "1") } `; export default function Page() { const { loading, data } = useQuery(query); // ... 其余逻辑 }
这样既解决了当前报错,也符合Next.js App Router与Apollo Client的最佳实践。
内容的提问来源于stack exchange,提问作者Coco
相关产品推荐
相关产品推荐

