Fix: Objects are not valid as a React child (found: [object Object])
Quick Answer
How to fix the React error 'Objects are not valid as a React child' caused by rendering plain objects, Date objects, Promises, or API responses directly in JSX.
The Error
You render a React component and your app crashes with this message:
Objects are not valid as a React child (found: [object Object]).
If you meant to render a collection of children, use an array instead.Sometimes the parenthetical gives you a more specific hint:
Objects are not valid as a React child (found: object with keys {name, age}).
If you meant to render a collection of children, use an array instead.Or with Dates:
Objects are not valid as a React child (found: [object Date]).This means you passed something to JSX that React does not know how to render. React can render strings, numbers, booleans (they render as nothing), null/undefined (also nothing), JSX elements, and arrays of the above. Plain JavaScript objects are not on that list. When React encounters one, it throws this error.
Why This Happens
JSX expressions inside curly braces ({}) must resolve to a renderable value. When you write {someVariable}, React calls its internal rendering logic on that value. If someVariable is a plain object like { name: "Alice", age: 30 }, React has no way to turn that into DOM nodes. It does not know whether you want to display the keys, the values, or something else entirely.
This error shows up in several common scenarios:
- Rendering an object directly instead of accessing its properties.
- Rendering a Date object without calling
.toString()or.toLocaleDateString(). - Rendering a Promise by calling an async function in JSX.
- Rendering an array of objects without mapping them to JSX elements.
- Rendering an API response without extracting the fields you need.
- Accidentally passing an object where a string is expected (e.g., inside a
<p>tag).
The fix depends on which scenario you are in. Each one is covered below.
Fix 1: Access Object Properties Instead of Rendering the Object
The most common cause. You have an object and you drop it straight into JSX:
Broken code:
function UserCard({ user }) {
return <div>{user}</div>;
}Here user is something like { name: "Alice", age: 30 }. React cannot render that.
Fixed code:
function UserCard({ user }) {
return (
<div>
<p>{user.name}</p>
<p>{user.age}</p>
</div>
);
}Access the individual properties you want to display. Strings and numbers are valid React children, so user.name and user.age render fine.
If you are not sure what shape your object has, log it first:
console.log("user:", user);
console.log("type:", typeof user);This tells you exactly what keys are available and helps you decide what to render.
Pro Tip: If you are dealing with deeply nested API responses, destructure the props you need at the top of the component. This makes it obvious which fields you are using and prevents accidental object rendering deeper in the JSX tree:
function UserCard({ user }) { const { name, age, email } = user; return ( <div> <p>{name}</p> <p>{age}</p> <p>{email}</p> </div> ); }
Fix 2: Convert Date Objects to Strings
A Date is an object. React cannot render it:
Broken code:
function EventInfo({ event }) {
return <p>Starts: {event.startDate}</p>;
}If event.startDate is a new Date(...), this throws the error.
Fixed code:
function EventInfo({ event }) {
return <p>Starts: {event.startDate.toLocaleDateString()}</p>;
}Other options depending on what format you need:
// Full date and time
{event.startDate.toLocaleString()}
// ISO format
{event.startDate.toISOString()}
// Just the time
{event.startDate.toLocaleTimeString()}
// Custom formatting with Intl
{new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(event.startDate)}The key point: always call a method that returns a string before putting a Date in JSX. The same applies to any object that has a meaningful .toString() method.
Fix 3: Do Not Call Async Functions Directly in JSX
Calling an async function returns a Promise. A Promise is an object. React cannot render it:
Broken code:
async function fetchUserName(id) {
const res = await fetch(`/api/users/${id}`);
const data = await res.json();
return data.name;
}
function UserLabel({ userId }) {
return <span>{fetchUserName(userId)}</span>;
}fetchUserName(userId) returns a Promise, not the resolved string. React sees the Promise object and throws.
Fixed code — use state and useEffect:
import { useState, useEffect } from "react";
function UserLabel({ userId }) {
const [name, setName] = useState("");
useEffect(() => {
let cancelled = false;
async function load() {
const res = await fetch(`/api/users/${userId}`);
const data = await res.json();
if (!cancelled) {
setName(data.name);
}
}
load();
return () => {
cancelled = true;
};
}, [userId]);
return <span>{name}</span>;
}The cancelled flag prevents state updates after unmount, which avoids the cannot update an unmounted component warning.
Note: Make sure your useEffect dependency array is correct. Passing the wrong dependencies can cause infinite loops or stale data.
React Server Components (Next.js App Router)
If you are using Next.js 13+ with the App Router, server components can be async:
// app/user/[id]/page.tsx — this is a Server Component
async function UserPage({ params }) {
const res = await fetch(`https://api.example.com/users/${params.id}`);
const user = await res.json();
return <h1>{user.name}</h1>;
}
export default UserPage;This works because the server resolves the async function before sending HTML to the client. But if you try the same thing in a client component (one with "use client" at the top), you get the objects-not-valid error because the client tries to render the Promise.
If you mix server and client components incorrectly, you can also run into hydration errors where the server-rendered HTML does not match the client output.
Fix 4: Map Arrays of Objects to JSX Elements
An array of strings or numbers renders fine in React. An array of objects does not:
Broken code:
function UserList({ users }) {
return <ul>{users}</ul>;
}If users is [{ name: "Alice" }, { name: "Bob" }], React tries to render each object and fails.
Fixed code:
function UserList({ users }) {
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}Use .map() to transform each object into a JSX element. Always include a unique key prop — use a stable identifier like user.id, not the array index (unless the list never reorders).
If your data does not have unique IDs, you can use the index as a last resort:
{users.map((user, index) => (
<li key={index}>{user.name}</li>
))}But be aware that index keys cause problems when items are added, removed, or reordered. React uses keys to track which elements changed, and index-based keys can lead to subtle state bugs and unnecessary re-renders.
Fix 5: Handle API Responses Correctly
API calls return nested objects. Rendering the raw response is a common mistake:
Broken code:
function Dashboard() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("/api/dashboard")
.then((res) => res.json())
.then(setData);
}, []);
return <div>{data}</div>;
}data is the entire parsed JSON response — an object. This throws.
Fixed code:
function Dashboard() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("/api/dashboard")
.then((res) => res.json())
.then(setData);
}, []);
if (!data) return <p>Loading...</p>;
return (
<div>
<h2>{data.title}</h2>
<p>Users: {data.userCount}</p>
<p>Revenue: ${data.revenue}</p>
</div>
);
}Two things changed:
- Null check before rendering. Before the fetch resolves,
dataisnull. Without the guard, you would get cannot read properties of undefined errors when accessingdata.title. - Rendering specific properties instead of the entire object.
Common Mistake: Some APIs wrap data in a nested
datakey — for example,{ data: { users: [...] }, meta: { page: 1 } }. If you dosetData(response)and then try{data.users}, you are actually looking atresponse.users, which isundefined. You need{data.data.users}or, better, extract it during the fetch:.then(res => res.json()).then(json => setData(json.data)).
Fix 6: Use JSON.stringify for Debugging
Sometimes you need to dump an object to the screen to see what you are working with. Use JSON.stringify:
function DebugView({ data }) {
return (
<pre>{JSON.stringify(data, null, 2)}</pre>
);
}The three arguments:
data— the object to serialize.null— no custom replacer function.2— indent with 2 spaces for readability.
This converts the object to a string, which React can render. Wrap it in <pre> to preserve formatting.
Warning: Do not leave JSON.stringify debugging in production code. It dumps raw data to the page, which can expose sensitive information and looks unprofessional. Use it only during development.
You can also create a reusable debug component:
function Debug({ value, label }) {
if (process.env.NODE_ENV === "production") return null;
return (
<details>
<summary>{label || "Debug"}</summary>
<pre style={{ fontSize: "12px", background: "#f0f0f0", padding: "8px" }}>
{JSON.stringify(value, null, 2)}
</pre>
</details>
);
}This auto-hides in production and uses a collapsible <details> element to keep the page clean during development.
Fix 7: Handle Conditional Rendering with Objects
Sometimes the error appears because a conditional expression evaluates to an object instead of null or a JSX element:
Broken code:
function Profile({ user }) {
return <div>{user && user.address}</div>;
}If user.address is an object like { street: "123 Main St", city: "Springfield" }, this renders the object and throws.
Fixed code:
function Profile({ user }) {
return (
<div>
{user && user.address && (
<p>{user.address.street}, {user.address.city}</p>
)}
</div>
);
}Always check the type of the value at the end of your conditional chain. If it is an object, render its properties or transform it into a string.
Another pattern that causes this: using the logical AND (&&) operator with a number 0:
{items.length && <ItemList items={items} />}When items is empty, items.length is 0, and React renders the number 0 on screen. While this does not throw the “objects not valid” error, it is a related rendering gotcha. Use a strict boolean check instead:
{items.length > 0 && <ItemList items={items} />}This pattern is also relevant when components re-render unexpectedly due to truthy/falsy misunderstandings.
Fix 8: Watch for State Initialized with Objects
If you initialize state with an object and try to render it directly:
Broken code:
function Settings() {
const [config, setConfig] = useState({ theme: "dark", lang: "en" });
return <p>Config: {config}</p>;
}Fixed code:
function Settings() {
const [config, setConfig] = useState({ theme: "dark", lang: "en" });
return (
<p>
Theme: {config.theme}, Language: {config.lang}
</p>
);
}If you are managing complex state objects and updating them frequently, make sure you are not accidentally calling hooks conditionally, which can cause state values to become misaligned and lead to unexpected objects in your render output.
Debugging Checklist
When you see this error and are not sure which value is the problem, follow these steps:
Read the error message carefully. React often tells you what it found:
(found: object with keys {name, age})or(found: [object Date]). This narrows down the culprit immediately.Check the component’s return statement. Look at every expression inside
{}. Any of them could be an object.Add console.log before the return. Log every variable you render:
function MyComponent({ data }) {
console.log("data:", data, "type:", typeof data);
console.log("is array:", Array.isArray(data));
return <div>{data}</div>;
}Check the React DevTools. Open the Components tab, find the component that is throwing, and inspect its props and state. Look for any value that is an object where you expected a string or number.
Look at your data source. If the data comes from an API, log the raw response. APIs often change their response format, wrapping values in nested objects or returning different types than you expected.
Check for type mismatches after refactoring. If you recently changed a prop from a string to an object (or vice versa), child components that still expect the old type will break.
Still Not Working?
If you have checked all the fixes above and the error persists:
Check third-party components. Some UI libraries expect specific prop types. Passing an object where a component expects a string causes this error inside the library’s render method. Check the library’s documentation for the correct prop types.
Check context values. If you are using React Context and the provider passes an object, any consumer that renders the context value directly will throw. Render specific properties from the context value instead.
Check error boundaries. If you have an error boundary higher in the tree, it might be catching and re-rendering an error object. Make sure the fallback UI does not try to render the error object directly — use
error.messageinstead.Check your build output. In rare cases, bundler issues (especially with SSR or hydration mismatches) can cause a value to be an object on the client but a string on the server. Clear your build cache and rebuild.
Use TypeScript. TypeScript catches most instances of this error at compile time. If a prop is typed as
stringand you pass an object, the compiler flags it before you ever run the app. If you are starting a new project or refactoring an existing one, adding TypeScript types to your component props eliminates this entire category of runtime errors.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: React Warning: Failed prop type
How to fix the React 'Warning: Failed prop type' error. Covers wrong prop types, missing required props, children type issues, shape and oneOf PropTypes, migrating to TypeScript, default props, and third-party component mismatches.
Fix: React TypeError: Cannot read property 'map' of undefined
How to fix React TypeError Cannot read property map of undefined caused by uninitialized state, async data loading, wrong API response structure, and missing default values.
Fix: React Cannot update a component while rendering a different component
How to fix React Cannot update a component while rendering a different component caused by setState during render, context updates in render, and Redux dispatch in render.
Fix: Invalid hook call. Hooks can only be called inside of the body of a function component
How to fix the React Invalid hook call error caused by mismatched React versions, duplicate React copies, calling hooks outside components, and class component usage.