Fix "Objects are not valid as a React child" Error in React

beginnerโš›๏ธ React2026-03-22| React 16+, Next.js, Create React App โ€” any JavaScript environment rendering JSX

Error Message

Objects are not valid as a React child. If you meant to render a collection of children, use an array instead.
#react#render#object#json

The Error

Your component throws this in the browser console:

Objects are not valid as a React child. If you meant to render a collection of children, use an array instead.

The app crashes or goes blank. The stack trace points somewhere inside your JSX โ€” but the real culprit is usually a few lines above that.

Root Cause

React knows how to render strings, numbers, booleans, arrays, and React elements. Plain JavaScript objects and Promises? It has no idea what to do with them. Pass one of those as a JSX child and React bails out with this error.

The usual suspects:

  • Rendering a whole object {user} instead of a field like {user.name}
  • Rendering a Date object โ€” new Date() is not a string, no matter how much it looks like one
  • Rendering a Promise โ€” you forgot to await that async call
  • Dumping a raw API response into JSX before drilling into the actual value
  • Calling Object.keys() or Object.entries() and forgetting to .map() over the result

How to Find the Exact Cause

Check the full error message in the browser console. React is surprisingly helpful here:

Error: Objects are not valid as a React child (found: object with keys {id, name, email}).

Those keys are your clue. Search your component for anywhere that shape of object flows into JSX.

Still not obvious? Drop a quick log just before your return:

console.log(typeof someVariable, someVariable);

If typeof says "object" and that variable ends up as a child โ€” you found it.

Fix 1 โ€” Access the Property, Not the Object

Nine times out of ten, this is the problem. You passed the entire object when you only needed one field.

// โŒ Wrong โ€” renders the entire user object
function UserCard({ user }) {
  return {user}
;
}

// โœ… Fixed โ€” render a specific property
function UserCard({ user }) {
  return {user.name}
;
}

Fix 2 โ€” Convert Date Objects to Strings

Date objects are not renderable. Pick a string method: .toLocaleDateString(), .toISOString(), or .toLocaleString() depending on how you want it formatted.

// โŒ Wrong
const createdAt = new Date(post.createdAt);
return {createdAt};

// โœ… Fixed
return {createdAt.toLocaleDateString()};

Fix 3 โ€” Await the Promise Before Rendering

Async functions return Promises. Call one without await and you get a Promise object back โ€” not the data inside it.

// โŒ Wrong โ€” fetchUser returns a Promise, not a user
function Profile() {
  const user = fetchUser();
  return {user.name}
;
}

// โœ… Fixed โ€” useEffect + useState handles the async lifecycle
function Profile() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser().then(setUser);
  }, []);

  if (!user) return Loading...
;
  return {user.name}
;
}

Fix 4 โ€” Stringify JSON for Debugging

Want to eyeball raw API data during development? Use JSON.stringify(). Passing the object directly won't work.

// โŒ Wrong โ€” renders the whole object
return ```
{data}
```;

// โœ… Fixed โ€” readable, indented JSON string
return ```
{JSON.stringify(data, null, 2)}
```;

Strip this out before shipping to production โ€” it's a debug tool, not UI.

Fix 5 โ€” Map Over Collections Correctly

Object.entries() returns an array of [key, value] pairs. That array is not automatically renderable โ€” you still need to .map() it into JSX elements.

// โŒ Wrong โ€” Object.entries returns an array of arrays, not JSX
const settings = { theme: 'dark', lang: 'en' };
return {Object.entries(settings)};

// โœ… Fixed โ€” each entry becomes a list item
return (
  
    {Object.entries(settings).map(([key, value]) => (
      - {key}: {value}
    ))}
  
);

Fix 6 โ€” Guard Against Unknown Value Types

Sometimes you don't control what shape a value arrives in โ€” especially with third-party APIs. Add a type check before rendering.

// โŒ Wrong โ€” crashes if response is an object, not a string
return {response}
;

// โœ… Safe โ€” only renders if it's actually a string or number
return {typeof response === 'string' ? response : null}
;

Verification

After the fix, three things should be true:

  • The error overlay in the browser is gone
  • The component renders without crashing
  • Your test suite passes: npm test or pnpm test

If the error persists, the object is probably coming from a different part of the component tree. Follow the keys listed in the error message โ€” they'll lead you there.

Prevention Tips

TypeScript catches this at compile time. Type a prop as string and TypeScript won't let you accidentally pass a User object in its place. This eliminates the entire class of bug before the browser ever sees it.

interface Props {
  name: string; // callers must pass a string, not an object
}

function Label({ name }: Props) {
  return {name};
}

Destructure API responses at the boundary. Pull out the fields you actually need right where the data enters your app โ€” before it spreads into components. For deeply nested or unfamiliar JSON, paste the response into JSON Formatter & Validator to visualize the structure and confirm which keys to target. Everything runs in the browser; nothing gets uploaded.

No TypeScript? Use PropTypes for lightweight runtime validation:

import PropTypes from 'prop-types';

UserCard.propTypes = {
  user: PropTypes.shape({
    name: PropTypes.string.isRequired,
  }).isRequired,
};

Related Error Notes