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

Next.js搭配Apollo时服务端获取URL参数作为GraphQL查询变量问题

核心解决方案

你遇到的问题本质是getServerSideProps运行在服务端,无法访问客户端的路由实例,且动态路由参数本身可以通过getServerSideProps的入参直接获取,不需要从组件侧导出变量。

第一步:修改页面的getServerSideProps逻辑

直接从getServerSideProps的上下文参数中取动态路由的slug值,删掉之前引入的写死的userQueryVars变量即可:

import App from "../../../components/App"
import Header from "../../../components/Header"
import UserProfile, {
  USER_QUERY,
} from "../../../components/UserProfile" // 删掉userQueryVars的引入
import { initializeApollo, addApolloState } from "../../../lib/apolloClient"

const UserProfilePage = () => (
  <App>
    <Header />
    <UserProfile />
  </App>
)

export async function getServerSideProps(context) {
  const apolloClient = initializeApollo()
  // 直接从上下文获取动态路由参数
  const slug = context.query.slug

  await apolloClient.query({
    query: USER_QUERY,
    variables: { slug },
  })

  return addApolloState(apolloClient, {
    props: {}
  })
}

export default UserProfilePage

第二步:优化组件的请求容错

给useQuery添加跳过逻辑,避免路由还没初始化完成时,slug为undefined触发GraphQL参数校验报错,同时删掉组件里没用的userQueryVars导出:

import { gql, useQuery } from "@apollo/client"
import ErrorMessage from "./ErrorMessage"
import { useRouter } from "next/router";

export const USER_QUERY = gql`
  query getUser($slug: String!) {
    user(slug: $slug) {
      id
      email
      firstName
      lastName
    }
  }
`
// 删掉没用的userQueryVars导出

export default function UserProfile() {
    const router = useRouter()
    const userSlug = router.query.slug

  const { loading, error, data } = useQuery(USER_QUERY, {
    variables: {slug: userSlug},
    // slug不存在时跳过请求,避免参数错误
    skip: !userSlug,
  })

  if (error) return <ErrorMessage message="加载用户信息出错" />
  if (loading) return <div>加载中</div>
  if (!data) return <div>无数据</div>

  const { user } = data

  return (
    <section>
      <div>
        <h3>
          {user.firstName} {user.lastName}
        </h3>
        <p>{user.email}</p>
      </div>
    </section>
  )
}

之前尝试报错的原因

  1. useRouter是仅客户端可用的Hook,只能在React组件的函数体内调用,你在组件顶层导出变量时调用,服务端编译阶段就会执行,自然会触发客户端环境限制报错。
  2. ES模块规范要求import、export语句必须出现在代码顶层,不能包裹在if等条件判断内,所以加环境判断再导出的写法不符合语法规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 10:57:04