Troubleshooting code to display post titles in a specific category, with discussion on iterating over posts and handling non-existent categories.
I can see the issue! The problem is in how you're accessing the posts array in your JSX. Let me break down what's happening:
In your GROQ query, "posts": *[_type == 'post' && references(^._id)]{title} returns an array of post objects, not a single object. So categoryData[0].posts is an array like [{title: "Post 1"}, {title: "Post 2"}].
When you write categoryData[0].posts.title, you're trying to access .title on an array, which is undefined.
Here's the fix:
export default function Category() {
let { categoryData } = useLoaderData();
return (
<div>
<div>{categoryData[0].title}</div>
{/* Map over the posts array */}
{categoryData[0].posts.map((post) => (
<div key={post._id}>{post.title}</div>
))}
</div>
);
}Additional improvements to your query:
- Add
_idto your posts projection so you have a unique key for React:
"posts": *[_type == 'post' && references(^._id)]{_id, title}- Your
order(publishedAt desc)is currently ordering the categories, not the posts. If you want to order posts by publish date, move it inside the posts subquery:
*[_type == "category" && slug.current == $slug]{
_id,
title,
slug,
description,
"posts": *[_type == 'post' && references(^._id)] | order(publishedAt desc) {_id, title, publishedAt}
}- Since you're filtering by slug (which should be unique), you could simplify by using
[0]in the query itself:
*[_type == "category" && slug.current == $slug][0]{
_id,
title,
slug,
description,
"posts": *[_type == 'post' && references(^._id)] | order(publishedAt desc) {_id, title, publishedAt}
}Then access it as categoryData.posts instead of categoryData[0].posts.
The key concept here is understanding GROQ projections - when you create a subquery like your posts query, it returns an array of documents, and you need to handle that array appropriately in your frontend code.
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.