React async component rendering Promise instead of data from Sanity query

10 replies
Last updated: Jan 28, 2026
Hi! Hope all is well. I'm having an issue whilst following a tutorial that I can't figure out and was hoping to get a bit of help understanding:Any help would be gladly appreciated!

Error here:

Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
code:

import Layout from "@/components/layout";

import { groq } from 'next-sanity'

import client from '@/lib/sanity/sanity.client';
`const query = groq``

*[_type == "home"] {

title

}
```


export default async function Home() {

const home = await client.fetch(query)

console.log(home)

return (

<Layout>


<h1>{home.title}</h1>


</Layout>

);

}

Schema:

import { defineType, defineField } from 'sanity'


export default defineType({

name: 'home',

type: 'document',

title: 'Home',

fields: [

defineField({

title: 'Title',

name: 'title',

type: 'string',

validation: (Rule) => Rule.required(),

}),


],

preview: {

select: {

title: 'title',

},

prepare({ title }) {

return {

subtitle: 'Home',

title,

}

},

},

})
AI Update

This is a common issue when working with Next.js App Router and Sanity! The error "Objects are not valid as a React child" happens because your GROQ query returns an array of documents, but you're trying to render home.title as if home is a single object.

Looking at your query:

*[_type == "home"] {
  title
}

This returns an array of all documents where _type == "home". Even if you only have one home document, it still returns an array like [{ title: "My Title" }].

Here are two solutions:

Option 1: Access the first item in the array

export default async function Home() {
  const home = await client.fetch(query)
  console.log(home)
  return (
    <Layout>
      <h1>{home[0]?.title}</h1>
    </Layout>
  );
}

Option 2: Modify your query to return a single document (recommended)

const query = groq`
  *[_type == "home"][0] {
    title
  }
`

export default async function Home() {
  const home = await client.fetch(query)
  console.log(home)
  return (
    <Layout>
      <h1>{home?.title}</h1>
    </Layout>
  );
}

The [0] at the end of the filter tells GROQ to return just the first matching document instead of an array. I've also added optional chaining (?.) as a safety measure in case the document doesn't exist.

Since you're using a singleton pattern (only one "home" document), Option 2 is cleaner and more semantic. Your console.log should now show a single object instead of an array, and the error will disappear!

Show original thread
10 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?