Query and display categories from Sanity blog post schema

5 replies
Last updated: Nov 29, 2025
Hey guys,
I’m building a blog using auto-generated Blog (schema).
How do I get blog post
categories and category and call them in div ?
/sidangkalam/src/pages/Homepage.js

import { Carousel } from 'react-bootstrap';

import { useState, useEffect } from "react"

import client from "../client"

import { Link } from 'react-router-dom';


export default function Homepage() {

const [posts, setPosts] = useState([])


useEffect(() => {

client.fetch(
``*[_type == "post"] {`

title,

slug,

body,

categories {

category -> {

title },

mainImage {

asset -> {

_id,

url

},

alt

}
`}``

).then((data) => setPosts(data)).catch(console.error)

}, [])

return (

<div>{post.categories.title}</div>

/sidangkalam/schemas/category.js


export default {

name: 'category',

title: 'Category',

type: 'document',

fields: [

{

name: 'title',

title: 'Title',

type: 'string',

},

{

name: 'description',

title: 'Description',

type: 'text',

},

],

}

Currently it gives me below error :

(anonymous function)
src/pages/Homepage.js:238

  235 |     alt={post.title}
  236 |   />
  237 |   
> 238 |   <span className="thumb-title">{post.categories.title} </span>
      | ^
  239 | </div>
  240 | <h5 className="font-weight-bold mt-3">
  241 | {post.title}

AI Update

Looking at your code, the issue is that categories is an array in the blog schema, not a single object. When you try to access post.categories.title, JavaScript can't find a title property directly on the array.

There are two ways to fix this:

Your current query has a syntax issue. The categories field should be dereferenced properly:

client.fetch(
  `*[_type == "post"] {
    title,
    slug,
    body,
    categories[]-> {
      title
    },
    mainImage {
      asset -> {
        _id,
        url
      },
      alt
    }
  }`
)

Notice the change: categories[]-> instead of categories { category -> {...} }. The []-> syntax dereferences all items in the array.

Then in your JSX, you can access the first category like this:

<span className="thumb-title">
  {post.categories && post.categories[0]?.title}
</span>

Or display all categories:

<span className="thumb-title">
  {post.categories?.map(cat => cat.title).join(', ')}
</span>

Option 2: Keep Your Query, Fix the JSX

If your current query structure is working (though it looks incorrect), you'd need to access it as an array:

<span className="thumb-title">
  {post.categories?.[0]?.category?.title}
</span>

Why This Happens

In Sanity's blog schema, categories is defined as an array of references:

{
  name: 'categories',
  type: 'array',
  of: [{type: 'reference', to: {type: 'category'}}]
}

This means a post can have multiple categories, so you always get an array back, even if there's only one category. You need to access array elements using bracket notation like categories[0] to get individual items.

The []-> operator in GROQ dereferences all items in an array of references, which is exactly what you need here to get the actual category documents with their titles.

Show original thread
5 replies

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?