How to pass non-slug string params from getStaticPaths to getStaticProps in Next.js?

61 replies
Last updated: Sep 8, 2022
0

I am trying to return in my params the values of the

slug
and
tags
, please notice that
tags
is not an array it's just a string.
export async function getStaticPaths() {
  const chapters = await client.fetch(
    `*[_type == "chapters" && defined(slug.current)] {
      "slug": slug.current,
      "tags": tags
    }`
  );
  return {
    paths: chapters.map((s : any) => ({params: {slug : s.slug,tags: s.tags}})),
    fallback: false,
  }
}
So when I try to get the
tags
value in my getStaticProps I get a null value, yet
slug
is not null.
export async function getStaticProps(context: any) {
  const { slug = "",tags="" } = context.params
  const suggestions = await client.fetch(`
  *[_type == "chapters" && tags == $tags][0]
`, { tags })
when I try to replace the
tags
value in getStaticProps with a defined value , it fetches the document successfully ,this means the
tags
value received from getStaticPaths is null. How can I solve this issue ?
AI Update

The issue you're experiencing is due to how Next.js handles dynamic routes. In Next.js, getStaticPaths can only return params that correspond to actual dynamic route segments in your file structure.

For example:

  • If your file is pages/[slug].js, you can only return { params: { slug: "..." } }
  • If your file is pages/[slug]/[tags].js, you can return { params: { slug: "...", tags: "..." } }

When you return extra params that don't match your file structure, Next.js simply ignores them, which is why tags comes through as null in getStaticProps.

Solutions:

Option 1: Change your file structure (if you want tags in the URL) If you want both slug and tags as URL parameters, rename your file to something like pages/[slug]/[tags].js:

export async function getStaticPaths() {
  const chapters = await client.fetch(
    `*[_type == "chapters" && defined(slug.current)] {
      "slug": slug.current,
      "tags": tags
    }`
  );
  return {
    paths: chapters.map((s: any) => ({
      params: { slug: s.slug, tags: s.tags }
    })),
    fallback: false,
  }
}

Option 2: Fetch tags in getStaticProps (recommended) Keep your current file structure and fetch the tags based on the slug:

export async function getStaticProps(context: any) {
  const { slug = "" } = context.params
  
  // First get the chapter with its tags
  const chapter = await client.fetch(`
    *[_type == "chapters" && slug.current == $slug][0] {
      tags
    }
  `, { slug })
  
  // Then use the tags value for your suggestions query
  const suggestions = await client.fetch(`
    *[_type == "chapters" && tags == $tags][0]
  `, { tags: chapter?.tags })
  
  return {
    props: { suggestions }
  }
}

Option 3: Use query parameters instead If tags don't need to be in the URL path, you could pass them as query parameters, but this doesn't work well with static generation.

Option 2 is typically the best approach since you're only generating paths based on slug, and you can fetch all related data (including tags) within getStaticProps using that slug.

Show original thread
61 replies
What is the path to that file in your project? Because that’s how we can figure out which params should be provided.
it's
/[slug]
That‘s it? Nothing else? Just
/pages/[slug].js
?
yes exactly !
But then where do you expect
tags
to come from exactly?
Because
context.params
contains your routing parameters. In that route of yours, there is only
slug
. Not
tags
.
oh
so how can I pass the
tags
as well ?
/[slug]/[tags].js
or something.
No, my idea is to get recommendation chapters in the same page !
so I have to fetch the exact same
tags
of all the document
getStaticPaths
is there to generate all the possible paths for the current route. Typically, if you have a route with a dynamic
slug
parameter, then your
getStaticPaths
function needs to return all the existing slugs so that Next.js can statically build all your pages.
I understand
Do you have any idea how possibly I can manipulate the code to receive
tags
values as well
There is not 2 ways: you need to have it as part of your path. That’s how Next.js work.
Otherwise, you may use the same page for both slugs and tags, but I wouldn’t recommend it because you could have conflicts. Essentially flatten both collections into one and treat it as a unique collection.
by collections you mean the multiple documents of
chapters
?
export async function getStaticPaths() {
  const chapters = await client.fetch(
    `*[_type == "chapters" && defined(slug.current)] {
      "slug": slug.current,
      "tags": tags
    }`
  )
  return {
    paths: chapters
      .map(chapter => [
        { params: { slug: chapter.slug } },
        { params: { slug: chapter.tags } },
      ])
      .flat(),
    fallback: false,
  }
}
the same problem !
Check the data from the query. If
tags
is null, it’s because it’s missing from your document maybe.
I tested the query it works perfectly
are you sure about this part ?
  { params: { slug: chapter.slug } },
  { params: { slug: chapter.tags } },
No because I’m still not exactly sure how your data works. The last version I sent treats both slugs and tags as potential slugs.
when I map the
chapters
query :
 chapters.map((s) =>{
  console.log(s.slug, s.tags)
 })

I get this
slug , tags values
each
slug
corresponded to a
tags
value
and that's why I want to send the
tags
value of each
slug
to the getStaticProps so I can fetch the documents
Right, and you want to be able to access a given page with either its slug or its tags, right?
right
it slug
Wait.
Only via the slug?
yes only via the slug
is it possible ?
Sure, but then I don’t get why you need tags at all.
In
getStaticProps
, you receive the slug and you can use it to query the right document.
Why do you need tags?
I have to use the tags so I can fetch a recommendation chapters in the UI
something lie : You might also like
Are
tags
shared across chapters?
yes ofc
AAaaaaaah.
Okay I finally get it.
Alright.
all chapters have tags
export async function getStaticProps(context: any) {
  const { slug } = context.params
  const chapter = await client.fetch(
    `*[_type == "chapters" && slug.current == $slug][0]`,
    { slug }
  )

  if (!chapter) return { notFound: true }

  const suggestions = await client.fetch(
    `*[_type == "chapters" && tags == $tags]`,
    { tags: chapter.tags }
  )

  return { props: { chapter, suggestions } }
}
So first you query the chapter document based on its slug, and then you query the related chapters based on the tags from the chapter.
AAAA
works magically !!
Thank you so much
Amazing. 😄
Took a while but we got there.
Yeah, I have to be more specific the next time
I'm glad we found a way. 🙂
By the way how can I filter the documents to fetch all the same
tags
but not the current one !
*[ _type == "chapters" && tags == $tags && slug.current != $slug ]
ah yeah I was trying
!==
instead
thanks.
hello
user B
🙂Could you try and use threads for your questions please, this way it is easier to help everyone and not spend time on things that are posted in multiple places and multiple times
🙏And wonderful
user F
was able to help you! 🥳

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?