iChido
iChido

Reputation: 4634

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

I am setting up a React app with a Rails backend. I am getting the error "Objects are not valid as a React child (found: object with keys {id, name, info, created_at, updated_at}). If you meant to render a collection of children, use an array instead."

This is what my data looks like:

[
    {
        "id": 1,
        "name": "Home Page",
        "info": "This little bit of info is being loaded from a Rails 
        API.",
        "created_at": "2018-09-18T16:39:22.184Z",
        "updated_at": "2018-09-18T16:39:22.184Z"
    }
]

My code is as follows:

import React from 'react';

class Home extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      homes: []
    };
  }

  componentDidMount() {
    fetch('http://localhost:3000/api/homes')
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            homes: result
          });
        },
        // error handler
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }

  render() {

    const { error, isLoaded, homes } = this.state;

    if (error) {
      return (
        <div className="col">
          Error: {error.message}
        </div>
      );
    } else if (!isLoaded) {
      return (
        <div className="col">
          Loading...
        </div>
      );
    } else {
      return (
        <div className="col">
          <h1>Mi Casa</h1>
          <p>This is my house y'all!</p>
          <p>Stuff: {homes}</p>
        </div>
      );
    }
  }
}

export default Home;

What am I doing wrong?

Upvotes: 319

Views: 1250801

Answers (30)

Arshaan
Arshaan

Reputation: 71

In my case (Next.js 14) adding a suspense component around the page that is fetching data did the job:

page.tsx:

...
const Home: FC = () => {
  return (
    <ScrollSnap>
      <Suspense>
        <Step1Section />
      </Suspense>
    </ScrollSnap>
...

Step1Section.tsx:

...
import { getItem } from "@/utils/get-item";

const Step1Section: FC = async () => {
  const data = await getItem();
...

Although my case would probably be different than yours since in the ScrollSnap component there is a Children.count(props.children) which is causing the error.

Upvotes: 0

Rushi Dave
Rushi Dave

Reputation: 17

I got a same error in starting of my project in react.So i add curly{} braces inside div tag in class rendering.And refresh it,after that i remove that curly braces and again refresh.At that time that error gone and code run successfully.

Upvotes: -2

Shallon Kobusinge
Shallon Kobusinge

Reputation: 575

Had the same error but with a different scenario. I had my state as

        this.state = {
        date: new Date()
    }

so when I was calling it in my Class Component I had

p>Date = {this.state.date}</p>

Instead of

p>Date = {this.state.date.toLocaleDateString()}</p>

Upvotes: 2

pkfan
pkfan

Reputation: 19

Got this error because render wrong data type as child

const myObj = {name: 'pkfan'}


<Error status='riase error'> { myObj } </Error> 

Above component give error, because (myObj) not valid child.

I accidently pass (Object) instead of (JSX), that's why, I got this error.

solved this after wasting a lot of time.

Upvotes: 1

RaySun
RaySun

Reputation: 249

if you want to display all the object without iterating then you must send the data as string value i.e

  <p>{variableName.toString()}</>

Upvotes: 6

Georgi Georgiev
Georgi Georgiev

Reputation: 362

I had a similar problem, I forgot to add curly brackets { } while accepting the arguments in the component.

I had this: const ServiceCard = (color, title, icon, subtitle) => (

Then I updated it to this: const ServiceCard = ({color, title, icon, subtitle}) => (

and it worked.

Upvotes: 5

Chuks Jr.
Chuks Jr.

Reputation: 503

In my case, I had

<IonListHeader>
  <IonLabel>
     Order {{index}}
  </IonLabel>
</IonListHeader>

instead of

<IonListHeader>
  <IonLabel>
     Order {index}
  </IonLabel>
</IonListHeader>

Double curly braces.

Upvotes: 4

nerkn
nerkn

Reputation: 1980

I am using faker.js I was expecting company field to be string but it is an array It was :

<div className='text-gray-400 text-sm'>works at {s.company}</div>

but instead should be

<div className='text-gray-400 text-sm'>works at {s.company.name}</div>

I think it is not programmers fault, world is unexpected place and it's data could be anything. React should point out exact error.

Upvotes: -1

Nishant Kumar
Nishant Kumar

Reputation: 955

I had the same issue then I realized that I made the dumbest mistake ever. I had made my component asynchronous, I mean I used the async keyword, something like this

const ComponentName = async () => {
  return <>
   <div>This a WRONG component</div>
 </>
}

Then after a lot of headaches and prays, I realized my dumb mistake and removed the async.

const ComponentName = () => {
  return <>
   <div>This a WRONG component</div>
 </>
}

Upvotes: 1

Oskari Lehtonen
Oskari Lehtonen

Reputation: 749

I had a similar error while I was creating a custom modal.

const CustomModal = (visible, modalText, modalHeader) => {}

Problem was that I forgot that functional components can have only one prop passed to them, according to the REACT documentation:

This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions. React docs

Therefore when we want to pass several variables we need to wrap them into an object or an Array and pass the pointer to that array or object. And destructure it on the component side before invoking the component. Alternatively we can use curly braces to indicate that we are sending an object with identical property names and variables that contain the value of those properties, like in the example here. And then define the function also to destructure upon arrival of the properties contained in the object.

const CustomModal = ({visible, modalText, modalHeader}) => {}

If you have multiple values to pass to the component, you should pass an object, thus curly brackets around its properties/variables (assuming they have the same name).

Upvotes: 70

AMMAR YASIR
AMMAR YASIR

Reputation: 169

This error occur to me when send Date object (for example timestamp in firebse) to React child components.

If you send it as value of a child component parameter you would be sending a complex Object and you may get the same error as stated above.

You must send that date as string value

        <p>{timestamp.toString()}</p>

should work fine like this.

Upvotes: 8

Rohinibabu
Rohinibabu

Reputation: 678

the issue is because you are trying to display the whole object instead of the keys inside the object.

For example: Data is

[
    {
        "status": "success",
        "count": 20511
    },
    {
        "status": "failure",
        "count": 1776
    }
]

Now, in the component read like below, this will work.

import React, { Component } from 'react';


export default class Display extends Component {

    render() {

        const { data } = this.props;

        return (
            <>
           
               {
                   data.map((value,key)=>
                       <div>{value.status}</div>
                       <div>{value.count}</div>
                   )
               }
            </>

        )
    }
}

Upvotes: 9

Shallon Kobusinge
Shallon Kobusinge

Reputation: 575

For my case I had

 return (
    <div >
      {updated.map((one) => {
        <div>
          <h2>{one.name}</h2>
        </div>
      })}

    </div>
  );

Then changed to

 return (
    <div >
      {updated.map((one,index) => {
        return (
          <div key={index}>
          <h2>{one.name}</h2>
          </div>
        )
      })}

    </div>
  );

The issue was that I had no return statement after the map function

Upvotes: 2

Chathu Rashmini
Chathu Rashmini

Reputation: 1

I had the same issue. In my case, I have not render the value of the item. My initial code was,

        keyExtractor={(item, index) => item.id}
        data={courseGoals} 
        renderItem={itemData => (
          <View style={styles.listitem}> 
              <Text>{itemData.item}</Text> 
          </View>
        )} 
      />

And I simply added '.value' and it worked!

        keyExtractor={(item, index) => item.id}
        data={courseGoals} 
        renderItem={itemData => (
          <View style={styles.listitem}> 
              <Text>{itemData.item.value}</Text> 
          </View>
        )} 
      />

Upvotes: 0

nikita kumari
nikita kumari

Reputation: 41

There is yet another scenerio I captured. I DOM to be rendered was dependent on some checks. So I initialized it with null and on Switch was giving value to it. And while returning just returned that DOM.

export function test() {
  let DOM = null;
  switch (conditions) {
    case 1: {
      DOM = <div>SOME DIV</div>;
    }
    case 2: {
      DOM = <div>SOME DIV2</div>;
    }
    default: {
      DOM = null;
    }
  }
  return { DOM }; // -----1 Problem was here
}

Resolution to it was just wrap it with <></>

return <>{DOM}</>

Upvotes: 0

utkarsh-k
utkarsh-k

Reputation: 993

I got the same error today but with a different scenario as compared to the scenario posted in this question. Hope the solution to below scenario helps someone.

The render function below is sufficient to understand my scenario and solution:

render() {
    let orderDetails = null;
    if(this.props.loading){
        orderDetails = <Spinner />;
    }
    if(this.props.orders.length == 0){
        orderDetails = null;
    }
    orderDetails = (
        <div>
            {
                this.props.orders && 
                this.props.orders.length > 0 && 
                this.props.orders.map(order => (
                <Order 
                    key={order.id}
                    ingredient={order.ingredients}
                    price={order.price} />
                ))
            }
        </div>
    );
    return orderDetails;
}

In above code snippet : If return orderDetails is sent as return {orderDetails} then the error posted in this question pops up despite the value of 'orderDetails' (value as <Spinner/> or null or JSX related to <Order /> component).

Error description : react-dom.development.js:57 Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {orderDetails}). If you meant to render a collection of children, use an array instead.

We cannot return a JavaScript object from a return call inside the render() method. The reason being React expects some JSX, false, null, undefined, true to render in the UI and NOT some JavaScript object that I am trying to render when I use return {orderDetails} and hence get the error as above.

VALID :

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

INVALID :

<div>{orderDetails}</div> // This is WRONG, orderDetails is an object and NOT a valid return value that React expects.

Edit: I also got this error on my company's test server used by QA's for their testing. I pointed my local code to that test server and tested the scenario in which this error was reported by QA team and found NO ERROR in my local machine. I got surprised. I re-checked multiple number of times, re-checked the scenario with QA team and I was doing right but still I was not able to replicate the issue. I consulted my fellow devs but still were not able to figure out the root cause. So keeping with the information in the error message I started scanning all the code I had deployed in my last deployment commit ( to be more specific last 4-5 commits because I suspected it could be there from last few deployments but was caught in the current deployment), especially all the components I had developed and found that there was a component - inside which there was no specified condition being met so it was returning NOTHING from it. So see below sample pseudo code. I hope it helps.

render () {
return (
    {this.props.condition1 && (
       return some jsx 1
    )}

    {this.props.condition1 && (
       return some jsx 2
    )})
}

If you see in above pseudo code if condition1 and condition2 are not met then this component will render NOTHING from it and ideally a react component must return some JSX, false, null, undefined, true from it.

Upvotes: 31

NIV
NIV

Reputation: 486

Same error but a different scenario. I intended to assign my custom functional component to layoutComponent prop of a 3rd party module.

Erroneous code:

customLayout = () => {
// function returning a component
}
//usage:
{customLayout}

Fix:

CustomLayout = () => {
// functional component
}
//usage:
<CustomLayout></CustomLayout>

Upvotes: 0

Onshop
Onshop

Reputation: 3095

I had this error when using the BigNumber library on a value before setting to UseState:

const { toBN } = web3.utils;
...
 setOwner0Balance(toBN(await getBalance(owner0)));

Upvotes: 0

VR7
VR7

Reputation: 112

Well in my case, the data which I wanted to render contained an Object inside that of the array so due to this it was giving error, so for other people out there please check your data also once and if it contains an object, you need to convert it to array to print all of its values or if you need a specific value then use.

My data :

body: " d fvsdv"
photo: "http://res.cloudinary.com/imvr7/image/upload/v1591563988/hhanfhiyalwnv231oweg.png"
postedby: {_id: "5edbf948cdfafc4e38e74081", name: "vit"}       
//this is the object I am talking about.
title: "c sx "
__v: 0
_id: "5edd56d7e64a9e58acfd499f"
__proto__: Object

To Print only a single value

<h5>{item.postedby.name}</h5>

Upvotes: 1

JOSEPH MANIA
JOSEPH MANIA

Reputation: 29

I had a similar problem but mine this worked. My output

But the mistake i had done was simple. In my contents wer more than two and i had forgoten to wrap as an array. I had not put carly braces.

import React from 'react'
import {Button} from './Button';
import {Link} from 'react-router-dom'
import './HeroSection.css';

function HeroSection({
    lightBg, topLine, lightText, lightTextDesc, headline, description, 
    buttonLabel, img,alt,imgStart}
) {
    return (
        <>
            <div className={lightBg? 'home__hero-section': 'home__hero-section darkBg'}>
                <div className='container'>
                    <div className="row home__hero-row" 
                    style={{display:'flex', flexDirection:imgStart==='start'?' row-reverse':'row'}}
                    >
                    <div className='col'>
                        <div className='home__hero-text-wrapper'>
                            <div className='topline'>{topLine}</div>
                            <h1 className={lightText? 'heading': 'heading dark'}>{headline}</h1>
 <p className={lightTextDesc? 'home__hero-subtitle': 'home__hero-subtitle dark'}> 
 {description}
 <Link to='/sign-up'>
     <Button buttonSize='btn--wide' buttonColor='blue'>
{buttonLabel}
     </Button>
 </Link>
 </p>
                        </div>

                    </div>

                    <div className='col'>
                        <div className='home__hero-img-wrapper'>
                      <img src={img} alt={alt} className='home_hero-img'/>
                        </div>
                    </div>
                    </div>

                </div>

            </div>

        </>
    );
}

export default HeroSection
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 0

HumbleBee
HumbleBee

Reputation: 341

I faced this exact error. On tracing the root cause of this issue, I found that the FRONTEND code (React) is making a call to API and showing the response on the page by accessing some property of that response! So in this case, there are two cases

  • Either that property does not exists in the response from backend (it'll throw different error) OR
  • The property from the backend response is a complex object (Object inside Object) which our frontend React component is trying to access, but unable to read because React needs either a STRING (by directly accessing the specifc property e.g. Object.property) Or array. [This Case]

So we received this error because the React was expecting the STRING but got the object (because you passed Object inside object).

Please check your Backend logic (API) which is sending the response.

Upvotes: 0

Ula
Ula

Reputation: 2748

I hope it will help someone else.

This error seems to occur also when you UNintentionally send a complex object that includes for example Date to React child components.

Example of it is passing to child component new Date('....') as follows:

 const data = {name: 'ABC', startDate: new Date('2011-11-11')}
 ...
 <GenInfo params={data}/>

If you send it as value of a child component parameter you would be sending a complex Object and you may get the same error as stated above.

Check if you are passing something similar (that generates complex Object under the hood). Instead you can send that date as string value and do new Date(string_date) in child component.

Upvotes: 15

Bhanu Prathap
Bhanu Prathap

Reputation: 41

Objects are not valid as a React child

I also got the same error but with different scenario. I was learning react useReducer hook and implemented a counter with increment, decrement and reset buttons and I was trying to display the count on to the screen but I was the above mentioned error.

In the code I had declared the count which is returned by useReducer hook as the object and I was directly trying to return it rather than the count property of it

I should actually return count.count and I was returning count only(object itself) not property.

We can stringify object and return the string also.

import React, { useReducer } from "react";

const initialState = {
count:0,
}
const reducer = (state, action) => {
    switch (action.type) {
        case 'increment':
            return {count:state.count + 1}
        case 'decrement':
            return {count:state.count - 1}
        case 'reset':
            return initialState
        default:
            return state
    }
}

function CounterWithReducer(props) {
  const [count, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      <h1>{count}</h1>
      <button onClick={()=>{dispatch({type:'increment'})}}>Increment</button>

      <button onClick={()=>{dispatch({type:"decrement"})}}>Decrement</button>
      <button onClick={()=>{dispatch({type:"reset"})}}>Reset</button>
    </>
  );
}

export default CounterWithReducer;

In the above code

{count}

This section (in the return part ) is where I did the mistake instead of count I need to use count.count

Summary is that if you trying to show object on to screen you can't either use JSON.stringify() or try to display any property of the object.

I am in early stage of my developer life please pardon me for any spelling mistakes if any.

Upvotes: 4

Vasanth
Vasanth

Reputation: 607

In My case, I had a added async at app.js like shown below.

const App = async() => {
return(
<Text>Hello world</Text>
)
}

But it was not necessary, when testing something I had added it and it was no longer required. After removing it, as shown below, things started working.

 const App =() => {
    return(
    <Text>Hello world</Text>
    )
}

Upvotes: 2

triple
triple

Reputation: 31

I had this issue when I was trying to render an object on a child component that was receiving props.

I fixed this when I realized that my code was trying to render an object and not the object key's value that I was trying to render.

Upvotes: 0

Abdulla Ababakre
Abdulla Ababakre

Reputation: 413

I also occured the error,and I sloved it by removing the curly braces,hope it will help someone else.

You can see that ,I did not put the con in the curly brace,and the error occured ,when I remove the burly brace , the error disappeared.

const modal = (props) => {
const { show, onClose } = props;

let con = <div className="modal" onClick={onClose}>
        {props.children}
        </div>;

return show === true ? (
    {con}
) : (
    <div>hello</div>
);

There are an article about the usage of the curly brace.click here

Upvotes: 2

Tuan Phan
Tuan Phan

Reputation: 981

In your state, home is initialized as an array homes: []

In your return, there is an attempt to render home (which is an array). <p>Stuff: {homes}</p>

Cannot be done this way --- If you want to render it, you need to render an array into each single item. For example: using map()

Ex: {home.map(item=>item)}

Upvotes: 1

azeem
azeem

Reputation: 361

I faced same issue but now i am happy to resolve this issue.

  1. npm i core-js
  2. put this line into the first line of your index.js file. import core-js

Upvotes: 0

tbs
tbs

Reputation: 480

Although not specific to the answer, this error mostly occurs when you mistakenly using a JavaScript expression inside a JavaScript context using {}

For example

let x=5;

export default function App(){ return( {x} ); };

Correct way to do this would be

let x=5;
export default function App(){ return( x ); };

Upvotes: 5

Wakas Abbasid
Wakas Abbasid

Reputation: 446

Just to add to the other options, I was trying to access a nested object within the main object through the dot method as in: this.state.arrayData.CompleteAdress.Location In this case Location is a nested object inside Complete address which is why i cant simply access it with the dot notation.

  • So if you're facing this same issue, try JSON.parse so that you access the nested object and then manipulate accordingly.

Upvotes: 0

Related Questions