Dynamic nested route with slug queries returning empty array in Next.js

2 replies
Last updated: Oct 4, 2022
Hi everyone!
I'm stuck on a tricky implementation of a dynamic nested route and am wondering if there may be a smarter way to go about what I'm trying to achieve. I have a feeling the issue lies in the way I'm writing my
slug.current
business for groq queries, but I'm not 100% sure.
As per the first screenshot, I have a route,
/residences/[slug]/contributions/[contributions].js
that features the contributions of a particular artist. A given artist ([slug]) may have 3-4 contributions that each should have their own link. For
[contributions].js
, I've set up my
getStaticPaths
as follows (referencing the artist + the reference to their contributions):

export async function getStaticPaths() {
  const data = await client.fetch(
    groq`*[_type == "artistesEnResidence" && defined(slug.current) && defined(contributionsEcrivain)] {
      "slug": slug.current,
      contributionsEcrivain[]->{
        "slug": slug.current,
      },
    }`
  );

  const pages = data.reduce((arr, item) => {
    item.contributionsEcrivain.forEach((c) => {
      const params = {
        slug: item.slug,
        contributions: c.slug,
      };
      arr.push({ params: params });
    });
    return arr;
  }, []);

  return {
    paths: pages.map((page) => page),
    fallback: true,
  };
}
In
getStaticProps
, rather than querying the artist -> their contributions, I just reference the contributions document type as follows:

export const residencesEcrivainQuery = groq`
  *[_type == "contributionsEcrivain" && defined(slug.current)][] {
    _id,
    title,
    associatedArtist[0]->{
      "slug": slug.current,
      title,
    },
    associatedNumero[0]->{
      "slug": slug.current,
      number
    },
    body,
    "slug": slug.current,
  }
`;
However when I do so, the output is an empty array (even though I'm getting output in Sanity's Vision tool). Why might that be the case?
AI Update

Looking at your code, I can spot the issue! In your getStaticProps query, you have an extra set of empty brackets [] that's causing problems:

*[_type == "contributionsEcrivain" && defined(slug.current)][] {

That [] after your filter is treating the result as an array and trying to slice it, which is likely returning an empty result. Remove it!

However, there's a bigger issue with your approach: you're fetching ALL contributions documents, not just the specific one for the current route. In getStaticProps, you need to filter by the specific contributions slug from the route params:

export async function getStaticProps({ params }) {
  const { slug, contributions } = params;
  
  const query = groq`
    *[_type == "contributionsEcrivain" && slug.current == $contributionsSlug][0] {
      _id,
      title,
      associatedArtist[0]->{
        "slug": slug.current,
        title,
      },
      associatedNumero[0]->{
        "slug": slug.current,
        number
      },
      body,
      "slug": slug.current,
    }
  `;
  
  const data = await client.fetch(query, { 
    contributionsSlug: contributions 
  });
  
  return {
    props: {
      contribution: data
    }
  };
}

Key changes:

  1. Removed the extra [] after the filter
  2. Added [0] at the end to get a single document instead of an array
  3. Used parameterized query with $contributionsSlug to filter for the specific contribution matching the route
  4. Passed the contributions param from the route to the query

You could also verify the artist matches to be extra safe:

*[_type == "contributionsEcrivain" 
  && slug.current == $contributionsSlug 
  && $artistSlug in associatedArtist[]->slug.current][0] {
  // ... rest of projection
}

And pass both slugs: { contributionsSlug: contributions, artistSlug: slug }

Your getStaticPaths logic looks solid - that's correctly building all the possible route combinations. The issue was just in how you were fetching the data for each specific page!

Show original thread
2 replies
I have also tried to manually infer
getStaticProps
data for
/residences/lucile-de-peslouan/contributions/cherry-bomb
like so:

export async function getStaticPaths() {
  const data = [
    {
      slug: "lucile-de-peslouan",
      contributions: "cherry-bomb",
    },
  ];
  return {
    paths: data.map((post) => ({
      params: {
        contributions: post.contributions,
        slug: post.slug,
      },
    })),
    fallback: true,
  };
But was met with the following error (presumably because the query is returning an array of 18 "contributions" objects):
Hey guys! I figured it out.
In my
getStaticProps
, I was not entering the
slug
value in
pageData
properly:

export async function getStaticProps({ params }) {
  console.log("params", params);

  const footerLogos = await client.fetch(footerLogoQuery);

  const pageData = await client.fetch(residencesEcrivainQuery, {
    contributions: params.contributions,
    slug: params.contributions,
  });

  return {
    props: {
      pageData,
      footerLogos,
    },
    revalidate: 10,
  };
}
I previously had it set to
slug: params.slug
. I had to pass in the right prop to the groq query:

*[_type == "contributionsEcrivain" && slug.current == $slug][0] {...}
Everything is working great now!!
knock on wood

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?