# React: “Objects are not valid as a React child”

> React: Objects are not valid as a React child (found: object with keys ...). Render a field, map an array, or format the date instead of the object.

Canonical: https://app369.com/fix/react-objects-are-not-valid-as-a-react-child/
Last updated: 2026-11-07

React stops with Objects are not valid as a React child (found: object with keys {id, name}), or Minified React error #31 in production. Somewhere JSX has {something} where something is a plain object, a Date or a Promise, and React does not know how to draw it. The keys in the message tell you which object it was.

**Short answer**

Find the {value} in JSX that holds an object, using the keys in the message. Render one of its fields ({user.name}), map an array of objects to elements, format a Date ({date.toLocaleDateString()}), or show JSON while debugging ({JSON.stringify(data)}). If the keys are $$typeof, type, props and similar, a React element is being passed where a value was expected, or two copies of React are installed (check npm ls react). If the message says [object Promise], an async function or component is being rendered where its result was expected: await the data first. API error objects ({ message, code }) cause it too: render error.message.

## **Why React can’t render it, and the fix**

1. 01 ### **Rendering a whole object instead of a field**
  > “Objects are not valid as a React child (found: %s). If you meant to render a collection of children, use an array instead.” [**React, Minified React error #31**](https://react.dev/errors/31) React can render strings, numbers, elements and arrays of those. A plain object is none of these. Pick the field you want to show. Double braces are a common version: <p>{{ name }}</p> (a habit from other template languages) passes an object literal, so use <p>{name}</p>.```
// 🔴 user is { id, name, email }
<p>{user}</p>

// ✅
<p>{user.name}</p>
```
2. 02 ### **A list of objects that was not mapped** An API that returns an array of objects, or an object keyed by id, has to be turned into elements first. Map it, with a stable key for each item.```
<ul>
  {orders.map((o) => (
    <li key={o.id}>{o.number}: {o.total}</li>
  ))}
</ul>

// object keyed by id
{Object.values(ordersById).map((o) => <Order key={o.id} order={o} />)}
```
3. 03 ### **A Date or an error object** A Date is an object, so {createdAt} fails once the string from the API is turned into a Date. Format it. The same goes for an error object stored in state: render error.message, not error.```
<time>{createdAt.toLocaleDateString()}</time>
{error && <p role="alert">{error.message}</p>}
```
4. 04 ### **A Promise or async component in client code** Calling an async function in JSX, or writing async function MyComponent() in a client component, gives React a Promise. Async components only work as React Server Components (for example in the Next.js App Router). In client code, load the data in an effect or a data library and render the result once it arrives.

Checked against the vendor’s docs on November 7, 2026: [React: Minified React error #31 (full message)](https://react.dev/errors/31).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****No issues worth fixing, no charge.**** If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

Related: [**React “unique key prop” warning**](https://app369.com/fix/react-each-child-unique-key/) · [**React “Maximum update depth exceeded”**](https://app369.com/fix/react-maximum-update-depth-exceeded/) · [**“Cannot read properties of undefined”**](https://app369.com/fix/cannot-read-properties-of-undefined/)

Questions

## **More on this error**

<details>

<summary>**What does “Minified React error #31” mean? **+</summary>

It is the same error in a production build, where React shortens messages. The react.dev/errors/31 page shows the full text. Run the app in development mode to see which component and which keys caused it.

</details>

<details>

<summary>**Can I render an object with JSON.stringify? **+</summary>

Yes, for debugging: {JSON.stringify(data, null, 2)} inside a pre element shows the whole object. For users, render the fields they need.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

A different error?

## **Describe it and get a written quote**

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)