10

I am using the official with-apollo example to create a nextjs frontend. I am trying to use the user's slug, which can be found in the url string to render the user profile. However, I am not able to use the url parameter (the slug) as a variable in the graphql query.

The Link to the user profile

<Link href={{ pathname: "/users/[slug]", query: { slug: user.slug } }}>

The user profile component

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

The user profile page

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

What I have tried so far (among a lot of other things):

  1. Using router:

    export const userQueryVars = { slug: router.query.slug, }

Error: You should only use "next/router" inside the client side of your app.

  1. Using router and checking that is it called on client side:

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

Error: 'import' and 'export' may only appear at the top level.

I would be very thankful for any kind of help!!

2
  • If your question has been answered, please make sure to accept an answer for further references. Commented Jul 25, 2021 at 18:08
  • For next js version 13 server components see this answer Commented Aug 5, 2023 at 12:16

3 Answers 3

13

When using getServerSideProps you can find your slug (and all other dynamic params if you have them) inside context.params:

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

  // Do whatever you need with `slug`
  // ...
}

If you use TypeScript you can follow this example from the docs to add types:

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
}
Sign up to request clarification or add additional context in comments.

3 Comments

Cannot thank you enough!! Exactly what I was searching for!
what is the type of context?? I am so frustrated, nowhere can I find the type of context.
8

App Router Solution

In the new NextJS App Router, you can access the query parameters by adding the params and searchParams props to your page.tsx file:

export default function page({
  params,
  searchParams,
}: {
  params: { slug: string }
  searchParams: { [key: string]: string | string[] | undefined }
}) {
}

Then you can read the searchParams directly. Source.

Comments

4

You can access search params on the server side by:

export function GET(request) {
    request.nextUrl.searchParams.get('search-key')
}

3 Comments

That is not the ask. the ask is to get the URL params from the current URL in the browser window not the URL parameters from the URL passed to a route hander
Answer doesn't answer OP's question. But helped me coming from google. Upvoted!
Also, for ts, be sure to use request: NextRequest instead of Request

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.