Fix the “Objects are not valid as a React child” error
By Flavio Copes
How to fix the Objects are not valid as a React child found object Promise error in the Next.js pages folder by removing async from your page component.
React raises this error when you ask it to render something it doesn’t know how to display. Valid children are strings, numbers, elements, and arrays of those. A plain object is not on that list. Neither is a promise.
The found: part of the message tells you exactly what React choked on.
I had this error in a React (Next.js) app:
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.
After some time trying to figure out what the error meant, I figured out I was exporting my page component as async because I copied it from another Next.js project where this is possible because of the use of the app folder:
export default async function Page() {
}
But it was not possible in the pages folder.
Removing async made it work:
export default function Page() {
}
Why does async cause this?
An async function always returns a promise. In the app folder, Next.js knows how to handle that, because Server Components can be async. In the pages folder, React just calls your component and tries to render whatever comes back.
What comes back is a Promise. That’s the [object Promise] in the error message.
Other ways to hit this error
You can trigger the same error without any async code. Rendering a plain object does it too:
const user = { name: 'Flavio', age: 40 }
return <p>{user}</p>
This fails with found: object with keys {name, age}. The fix is to render the individual properties:
return <p>{user.name}</p>
A Date object is another common one. React won’t render it directly, so you convert it to a string first:
return <p>{new Date().toLocaleDateString()}</p>
How to track it down
Read the found: part carefully. If it says [object Promise], look for an async component or a fetch call you forgot to await properly. If it lists object keys, search your JSX for a variable holding that object.
While debugging, wrapping the value in JSON.stringify() lets you see what you’re actually dealing with:
return <p>{JSON.stringify(user)}</p>
That’s not a fix, but it turns a crash into visible output, and from there the real fix is usually obvious.