Next.js 13.5.2集成Apollo Client时路由实例缺失报错求助
问题解决:Next.js 13.5.2 + Apollo Client 路由实例缺失报错
问题原因
next/router 仅能在客户端组件中使用,你的Apollo Client配置文件(withApollo.tsx)可能在服务器端渲染流程中被执行。即使添加了typeof window !== "undefined"的判断,模块级别的import Router from "next/router"语句会先在服务器端被处理,此时不存在路由实例,直接触发"No router instance found"错误。
解决方案
方案1:动态导入Router(推荐)
将Router的导入改为运行时动态导入,确保仅在客户端环境下加载路由模块:
import { onError } from "@apollo/client/link/error"; const ErrorLink = onError(async ({ graphQLErrors, networkError }) => { if (graphQLErrors) { for (const err of graphQLErrors) { console.log( `[GraphQL error]: Message: ${err.message}, Location: ${err.locations}, Path: ${err.path}` ); if (err.message.includes("not authenticated") && typeof window !== "undefined") { // 动态导入next/router,仅在客户端执行 const { default: Router } = await import("next/router"); Router.push("/login"); } } } if (networkError) console.log(`[Network error]: ${networkError}`); });
方案2:拆分Apollo Client的客户端/服务器端配置
如果你的Apollo Client在服务器端(如getServerSideProps)和客户端都需要初始化,可将Error Link仅添加到客户端的Apollo配置中:
// withApollo.tsx import { ApolloClient, InMemoryCache, createHttpLink, from } from "@apollo/client"; import { onError } from "@apollo/client/link/error"; function createApolloClient(isServer: boolean) { const links = [createHttpLink({ uri: "/api/graphql" })]; // 仅在客户端添加Error Link if (!isServer) { const ErrorLink = onError(async ({ graphQLErrors }) => { if (graphQLErrors) { for (const err of graphQLErrors) { if (err.message.includes("not authenticated")) { const { default: Router } = await import("next/router"); Router.push("/login"); } } } }); links.unshift(ErrorLink); } return new ApolloClient({ ssrMode: isServer, link: from(links), cache: new InMemoryCache(), }); } export default createApolloClient;
方案3:改用App Router的路由方式(若使用App Router)
如果你使用的是Next.js 13+的App Router,应替换next/router为next/navigation的useRouter钩子。由于Apollo Link无法直接使用React Hooks,可在页面组件中捕获Apollo错误并跳转:
// 客户端组件中使用useQuery "use client"; import { useQuery } from "@apollo/client"; import { useRouter } from "next/navigation"; import { GET_DATA } from "../queries"; export default function MyPage() { const router = useRouter(); const { error } = useQuery(GET_DATA); if (error?.graphQLErrors?.some(err => err.message.includes("not authenticated"))) { router.push("/login"); } // 页面内容... }
验证
修改后,触发"not authenticated"错误时,客户端应能正确跳转到登录页,且服务器端不再抛出路由实例缺失的错误。
内容的提问来源于stack exchange,提问作者Gerardo Trujillo
相关产品推荐
相关产品推荐

