👋 Next.js Conf 2024: Come build, party, run, and connect with us! See all events

Help with filtering blogs by category in Next.js using Groq

9 replies
Last updated: Jun 28, 2022
hey all, Im stuck on this issue please help me to solve this. So I have multiple categories in Blogs. So I want to print Blogs related to the category. On the
category
page But It's not working. and how I add two params in getStaticProps. the slug param is working good but How do I add $Id. Blogs are filtering via Id but how add it on the frontend. On
GROQ
Playground all the blogs are filtering fine. But I'm stuck how I filter on frontend. How I pass $id

/**
 * Makes Next.js aware of all the slugs it can expect at this route
 */
export async function getStaticPaths() {
  const allCategoryQuery = groq`
  *[_type == "blogCategory" && defined(slug.current)][].slug.current
`;

  const pages = await getClient().fetch(allCategoryQuery);
  return {
    paths: pages.map((slug) => `/blog/category/${slug}`),
    fallback: true,
  };
}

export async function getStaticProps({ params, preview = false }) {
  const query = groq`
  *[_type == "blogCategory" && slug.current == $slug]{
    _id,title,description,slug,image,
     "blogCategory": *[_type=='article' &&  blogCategories[]._ref == "1b65f627-7d10-4a35-9062-41e9245ff272"]
   }
  `;

  const queryParams = { slug: params.slug };
  console.log(queryParams, 'queryParams');

  const data = await getClient(preview).fetch(query, queryParams);

  // Helper function to reduce all returned documents down to just one
  const page = filterDataToSingleItem(data, preview);
  return {
    props: {
      preview,
      siteSettings: await fetchGlobalSettings(),
      allCategories: await sanity.fetch(groq`
      *[_type == "blogCategory" && !(_id in path('drafts.**'))] {...}`),
      data: {
        page,
        query,
        queryParams,
      },
    },
  };
}
Currently Id is 1b65f627-7d10-4a35-9062-41e9245ff272 and Localhost Url is
http://localhost:3000/blog/category/first-category .
const BlogView = (props) => {
  const { data, preview, siteSettings = {}, allCategories } = props;

  const { data: previewData } = usePreviewSubscription(data?.query, {
    params: data?.queryParams ?? {},
    initialData: data?.page,
    enabled: preview,
  });
  // Client-side uses the same query, so we may need to filter it down again
  const page = filterDataToSingleItem(previewData, preview);
  if (!page) return null;

  return (
    <Layout siteSettingData={siteSettings}>
      {page &&
        page.blogCategory.map((item, i) => (
          <BlogItem data={item} key={item._id || i} />
        ))}
    </Layout>
  );
};

export default BlogView;
Jun 27, 2022, 12:26 PM
There are quite a few things to unpack here. First of all, your
getStaticPaths
does not return the right data. It should return an array of object with a
params
property, not actual paths as strings. Something like this:
[
  { params: { slug: 'category-1' } },
  { params: { slug: 'category-2' } },
  { params: { slug: 'category-3' } },
]
Regarding
getStaticProps
, I think you’re making your life too difficult. You receive a category slug from the parameter. All you want are all the posts whose category has this slug. Without knowing your schema, I would say something like this:
*[ _type == "article" && $slug in blogCategories[]->slug.current]
Then, I’m not sure you should be reducing all your data to a single entry. Ultimately you want a collection or blog posts for that category, don’t you?
Jun 27, 2022, 12:32 PM
Is there any way to add query params like this in getStaticProps? I tries this in getserverSide props its working fine for me. But In getstaticprops its throwing error call id is undefined
Jun 27, 2022, 12:35 PM
Well you receive the route params in the
params
object. So if your page is called
[slug].js
, you receive
{ params: { slug: 'foo' } }
.
Jun 27, 2022, 12:36 PM
Thank you for help all working ......

/**
 * Makes Next.js aware of all the slugs it can expect at this route
 */
export async function getStaticPaths() {
  const allSlugsQuery = groq`*[_type == "article" && defined(slug.current)][].slug.current`;
  const pages = await getClient().fetch(allSlugsQuery);

  return {
    paths: pages.map((slug) => `/blog/${slug}`),
    fallback: true,
  };
}

export async function getStaticProps({ params, preview = false }) {
  const query = groq`
  *[_type == "article" && slug.current == $slug]
  { ...,
  "id": _id,author->{avatar,name,description,twitter},
  "blogCategories":blogCategories[]->{title,image,slug,description,slug,
  ${fetchContentBlocks}
  }
}
`;
  const queryParams = { slug: params.slug };
  const data = await getClient(preview).fetch(query, queryParams);
  // console.log('data', data);

  // Escape hatch, if our query failed to return data
  if (!data) return { notFound: true };

  // Helper function to reduce all returned documents down to just one
  const page = filterDataToSingleItem(data, preview);

  return {
    props: {
      preview,
      data: {
        query,
        queryParams,
        page,
        siteSettings: await fetchGlobalSettings(),
      },
    },
  };
}

Jun 27, 2022, 3:36 PM
Thank you all working now .....

/**
 * Makes Next.js aware of all the slugs it can expect at this route
 */
export async function getStaticPaths() {
  const allCategoryQuery = groq`
  *[_type == "blogCategory" && defined(slug.current)][].slug.current
`;

  const pages = await getClient().fetch(allCategoryQuery);
  return {
    paths: pages.map((slug) => `/blog/category/${slug}`),
    fallback: true,
  };
}

export async function getStaticProps({ params, preview = false }) {
  const query = groq`
  *[_type == "blogCategory" && slug.current == $slug]
  {...,
  "relatedBlogs":*[ _type == "article" && $slug in blogCategories[]->slug.current]}
`;

  const queryParams = { slug: params.slug };
  const data = await getClient(preview).fetch(query, queryParams);
  if (!data) return { notFound: true };

  // Helper function to reduce all returned documents down to just one
  const page = filterDataToSingleItem(data, preview);
  return {
    props: {
      preview,
      siteSettings: await fetchGlobalSettings(),
      allCategories: await sanity.fetch(groq`
       *[_type == "blogCategory" && !(_id in path('drafts.**'))] {...}`),
      data: {
        page,
        query,
        queryParams,
      },
    },
  };
}

Jun 27, 2022, 3:37 PM
Is there any way to speed up the blog page?Speed is slow minor slow but ok
can you please help in this??

Im using getstaticprops.
Jun 27, 2022, 3:39 PM
I guess it depends a lot what is the performance bottleneck. First, make sure you’re not assuming that just from your local environment, because it will always be significantly slower than production.
Jun 28, 2022, 7:14 AM
Ok thanks you.
Jun 28, 2022, 9:26 PM
yes its working very fast on prouction. thanks.
Jun 28, 2022, 9:27 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?