Nextjs - 在服务器端访问 url 参数

kam*_*hen 9 javascript apollo reactjs next.js

我正在使用官方的with-apollo示例来创建 nextjs 前端。我正在尝试使用用户的 slug,它可以在 url 字符串中找到来呈现用户配置文件。但是,我无法使用 url 参数(slug)作为 graphql 查询中的变量。

用户个人资料的链接

<Link href={{ pathname: "/users/[slug]", query: { slug: user.slug } }}>
Run Code Online (Sandbox Code Playgroud)

用户配置文件组件

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
    }
  }
`

// I can not get this to work using url parameters
export const userQueryVars = {
  slug: "userSlug", // This should be a url parameter!!
}

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

  const { loading, error, data } = useQuery(USER_QUERY, {
    variables: {slug: userSlug},
  })

  if (error) return <ErrorMessage message="Error loading users." />
  if (loading) return <div>Loading</div>
  if (!data) return <div>No data</div>

  const { user } = data

  return (
    <section>
      <div>
        <h3>
          {user.firstName} {user.lastName}
        </h3>
        <p>{user.email}</p>
      </div>
    </section>
  )
}
Run Code Online (Sandbox Code Playgroud)

用户个人资料页面

import App from "../../../components/App"
import Header from "../../../components/Header"
import UserProfile, {
  USER_QUERY,
  userQueryVars,
} from "../../../components/UserProfile"
import { initializeApollo, addApolloState } from "../../../lib/apolloClient"

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

export async function getServerSideProps() {
  const apolloClient = initializeApollo()

  await apolloClient.query({
    query: USER_QUERY,
    variables: userQueryVars, // This is passed from the component!
  })

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

export default UserProfilePage
Run Code Online (Sandbox Code Playgroud)

到目前为止我已经尝试过的(还有很多其他的事情):

  1. 使用路由器:

    导出 const userQueryVars = { slug: router.query.slug, }

错误:您应该只在应用程序的客户端内使用“next/router”。

  1. 使用路由器并检查它是否在客户端被调用:

    if (process.browser) { 导出 const userQueryVars = { slug: router.query.slug, } }

错误:“导入”和“导出”可能仅出现在顶层。

我将非常感谢任何形式的帮助!

Dan*_*ila 12

使用时,getServerSideProps您可以在其中找到您的slug(以及所有其他动态参数,如果有的话)context.params

export async function getServerSideProps(context) {
  const  { slug } = context.params;

  // Do whatever you need with `slug`
  // ...
}
Run Code Online (Sandbox Code Playgroud)

如果您使用 TypeScript,您可以按照文档中的示例添加类型:

import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'
 
type Repo = {
  name: string
  stargazers_count: number
}
 
export const getServerSideProps: GetServerSideProps<{
  repo: Repo
}> = async () => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}
 
export default function Page({
  repo,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
  return repo.stargazers_count
}
Run Code Online (Sandbox Code Playgroud)

  • 上下文的类型是什么?我很沮丧,无处可找到上下文类型。 (2认同)