Troubleshooting code to display post titles in a specific category, with discussion on iterating over posts and handling non-existent categories.

23 replies
Last updated: Sep 20, 2022
Trying to display titles of posts in a specific category but can't get it to work.My code:

export const loader: LoaderFunction = async ({ params }) => {
  const categoryData = await getClient().fetch(
    `*[_type == "category" && slug.current == $slug]{ 
      _id, 
      title, 
      slug,
      description,
      "posts": *[_type == 'post' && references(^._id)]{title}
    } | order(publishedAt desc) `,
    { slug: params.slug }
  );

  return { categoryData };
};

export default function Category() {
  let { categoryData } = useLoaderData();

  return (
    <div>
      <div>{categoryData[0].title}</div>
      <div>{categoryData[0].posts.title}</div>
    </div>
  );
}
The error I'm getting: TypeError: Cannot read properties of undefined (reading 'title')

Any help as to what I'm doing wrong? Have looked at the documentation, but there's not much there on frontend output
Sep 20, 2022, 9:51 PM
Also, this is my category schema, which I think might be the issue?
name: "category",
  title: "Category",
  type: "document",
  fields: [
    {
      name: "title",
      title: "Title",
      type: "string",
    },
    {
      name: "slug",
      type: "slug",
      title: "Slug",
      options: {
        source: "title",
      },
    },
    {
      name: "description",
      title: "Description",
      type: "text",
    },
  ],
};
Sep 20, 2022, 9:53 PM
If you run that query in the Vision plugin in your Studio do you get the expected output for posts?
Sep 20, 2022, 10:07 PM
user M
I get this:
param $slug referenced, but not provided
*[_type == "category" && slug.current == $slug]{ 
-----------------------------------------^^^^
Line:   0
Column: 41
Running:

*[_type == "category" && slug.current == $slug]{ 
			_id, 
			title, 
			slug,
			description,
			"posts": *[_type == 'post' && references(^._id)]{title},
		}
Sep 20, 2022, 10:13 PM
I will mention, that this query on my website does put out the category title. I just can't seem to get a post title to show up
Sep 20, 2022, 10:14 PM
Ah, are you providing your params?
Sep 20, 2022, 10:18 PM
I am
Sep 20, 2022, 10:18 PM
Here, without the $slug, my vision fetch does return the data I'm looking for
Sep 20, 2022, 10:19 PM
OK, cool so the query isn't the issue. If you try to log out your data after this line:
let { categoryData } = useLoaderData();
is it properly fetching your data?
Sep 20, 2022, 10:20 PM
your category posts are being returned as an array
Sep 20, 2022, 10:20 PM
{categoryDate[0].posts.title}
is assuming posts is an object with a title key
Sep 20, 2022, 10:21 PM
woops, typo, but you get it, I think!
Sep 20, 2022, 10:22 PM
user V
ok, so what do I do to fix it?
Sep 20, 2022, 10:22 PM
you need to iterate over the posts… something like
Sep 20, 2022, 10:22 PM
{categoryData[0].posts.map(p => p.title)}
Sep 20, 2022, 10:22 PM
user M
Yes, it is properly fetching the data for the current category
Sep 20, 2022, 10:24 PM
user V
Got it! Thank you!
Sep 20, 2022, 10:28 PM
user V
do I have to use p? might be a stupid question
Sep 20, 2022, 10:29 PM
user L
you can name that variable whatever you like!
Sep 20, 2022, 10:31 PM
Yeeeee haw! Thanks everyone!
Sep 20, 2022, 10:32 PM
user M
/
user V
here's a quick add on question, if I wanted my website to display "Category not found" in case someone entered a non existent category, would that be done through GROQ or through...?
Sep 20, 2022, 10:34 PM
You'd need to query for that category to check if it exists, but the 'Category not found' text would be something you handled on your frontend. You'd need some sort of conditional to check if the query returned an empty array and if so, render that text.
Sep 20, 2022, 10:37 PM
Awesome, thank you
Sep 20, 2022, 10:37 PM
You're welcome!
Sep 20, 2022, 10:43 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?