Issue with rendering a React component in a tutorial, resolved with assistance from Maciej.

10 replies
Last updated: Feb 16, 2023
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!

Hey User, the problem here seems to be that you are trying to make the react component itself asynchronous which won’t work. Instead you need to create a state for home title, put the asynchronous call into a useEffect where you await the data and set the home title state.
Also, I highly recommend putting these types of questions into chat gpt since it can solve it for you 🙂
Hi User! It's odd to me I'm following a tutorial and this is how it's working. I'm new to react so I'm not sure entirely how to do so. ChatGPT is at capacity right now 😅. I used to get around with incognito mode but that seems to be patched up now.Would you happen to know some working code I code use in the meantime to get around this error?
Huh, weird I’m in without a problem 🙂Here’s what the chat came up with:

import Layout from "@/components/layout";
import { groq } from 'next-sanity'
import client from '@/lib/sanity/sanity.client';
import { useEffect, useState } from 'react';

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

export default function Home() {
  const [home, setHome] = useState(null);

  useEffect(() => {
    const fetchHome = async () => {
      const data = await client.fetch(query);
      setHome(data[0]);
    };
    fetchHome();
  }, []);

  if (!home) {
    return <div>Loading...</div>;
  }

  return (
    <Layout>
      <h1>{home.title}</h1>
    </Layout>
  );
}
Right, I will continue to try refreshing, I really appreciate your assistance!I'm a bit warmer, now the error page went away and I can see the page being rendered. The object is being logged to the console.
I forgot to mention I'm using Typescript. There's currently an error under the &lt;h1&gt;{home.title}&lt;/h1&gt; that states: Property 'title' does not exist on type 'never'.
Assuming I need something like this?type Props = {
title: string
}
yes you would set that as the state type and fetch return type
import Layout from "@/components/layout";
import { groq } from 'next-sanity'
import client from '@/lib/sanity/sanity.client';
import { useEffect, useState } from 'react';

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

type HomeType = {
  title: string
}

export default function Home() {
  const [home, setHome] = useState<HomeType | null>(null);

  useEffect(() => {
    const fetchHome = async () => {
      const data = await client.fetch<HomeType[]>(query);
      setHome(data[0]);
    };
    fetchHome();
  }, []);

  if (!home) {
    return <div>Loading...</div>;
  }

  return (
    <Layout>
      <h1>{home.title}</h1>
    </Layout>
  );
}
You've completely made my morning! Greetings from Boston User!!Have a wonderful rest of your day!
glad I could help, have a great day 🙂

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?