0

I created a blog using React & Sanity but I couldn't find how to get the blogpost categories or category.

import {useState, useEffect} from "react"
import { Link, useParams } from "react-router-dom"
import client from "../client"
import BlockContent from "@sanity/block-content-to-react"

export default function SinglePost() {
    const [singlePost, setSinglePost] = useState([])
    const [isLoading, setIsLoading] = useState(true)
    const { slug } = useParams()
    

    useEffect(() => {
        client
          .fetch(
            `*[slug.current == "${slug}"] {
            title,
            body,
            categories {
                category -> {
                name
            },
            mainImage {
              asset -> {
                _id,
                url
              },
              alt
            }
          }`
          )
          .then((data) => setSinglePost(data[0]))
        setIsLoading(false)
      }, [slug])

    return (
        <div>
        <h2>{singlePost.categories.category.name}</h2>
        </div>

Error : TypeError: Cannot read properties of undefined (reading 'category')

3 Answers3

1

I created two useEffects, one for the post content and one for the categories for each post.

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

useEffect(() => {
    client
    .fetch(
        `*[_type == "post"] {
        title,
        slug,
        body,
        mainImage {
        asset -> {
            _id,
            url
        },
        alt
        },
        publishedAt
    }`
    )
    .then((data) => setPosts(data))
    .catch(console.error)
}, [])

useEffect(() => {
    client
    .fetch(
        `*[_type == "category"] {
        title,
    }`
    )
    .then((data) => setCategory(data))
    .catch(console.error)
}, [])

Then to display the categories for the post, use the following code:

{categories.map((category) => (
    <div className = "flex flex-wrap justify-center">                                    
        <p>{category.title}</p>
    </div>
))}
Brandon Pyle
  • 307
  • 3
  • 14
0

What is your schema? Is categories a single object, or an array? If it's an array, you will need to do:

categories[] {
  category-> { name }
}

Then in your JSX, something like:

<h2>{singlePost.categories.map { |c| c.category.name }.join(", ")</h2>
Alexander Staubo
  • 3,148
  • 2
  • 25
  • 22
0

If you want to get the categories for each post. You should use groq

import groq from 'groq'
useEffect(() => {
        client
          .fetch(
            groc`*[slug.current == "${slug}"] {
            title,
            body,
            categories[]-> {
                title
            },
            mainImage {
              asset -> {
                _id,
                url
              },
              alt
            }
          }`
          )
          .then((data) => setSinglePost(data[0]))
        setIsLoading(false)
      }, [slug])

You can find more information about this here: https://www.sanity.io/blog/build-your-own-blog-with-sanity-and-next-js

anne
  • 1