Query and display categories from Sanity blog post schema

5 replies
Last updated: Dec 17, 2021
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
Thanks for your response
user M
but &lt;span className=“thumb-title”&gt;{post.categories.title}&lt;/span&gt; didn’t return anything.
How do you call it in html ?
😅
Thanks for your response but &lt;span className=“thumb-title”&gt;{post.categories.title}&lt;/span&gt; didn’t return anything.
How do you call it in html ?
😅
Hmm, are you sure your query is returning results? If you
console.log
it, what do you get?
Hmm, are you sure your query is returning results? If you
console.log
it, what do you get?
I had found solution for this one. Thanks!

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?