Vishwa Punchihewa
Vishwa Punchihewa

Reputation: 41

Objects are not valid as a React child (Conversion of object to String)

The development server displays the following error when running the React Code "Objects are not valid as a React child (found: object with keys {_seconds, _nanoseconds}). If you meant to render a collection of children, use an array instead."

The error is shown in the following line

this.setState({screams:res.data});

However, research of similar problems shows that the error occurs when passing the object as a property

Home Page

class home extends Component {
    state={
        screams : null
    };
    componentDidMount(){
        axios.get('/screams')
        .then(res=>{
            console.log(res.data);
            *this.setState({
                screams:res.data               
            });*

        })
        .catch(err=>console.log(err));
    }
    render() {
        let recentScreamsMarkup= this.state.screams ? (
            this.state.screams.map((scream) => <Scream scream={scream}/>)
            ) : <p>Loading...</p>
        return(
            <Grid container spacing={5}>
                <Grid item sm={8} xs={12}>
                    {recentScreamsMarkup}
                </Grid>
                <Grid item sm={4} xs={12}>
                    <p>Profile</p>
                </Grid>
            </Grid>
        );
    }
}

The Scream Component

 class Scream extends Component {
    render() {
        const {classes, scream:{meme,translation,userImage,userHandle,createdAt,screamId,likeCount,commentCount} }=this.props;
        return (
            <Card>
                <CardMedia
                image={userImage}
                title="Profile Image"/>
                <CardContent>
                    <Typography variant="h5">{userHandle}</Typography>
                    <Typography variant="body1" color="main">{createdAt}</Typography>
                    <Typography variant="body2">{meme}</Typography>
                    <Typography variant="body2">{translation}</Typography>
                </CardContent>
            </Card>  
        )
    }
}

I believe that the solution has something to do with JSON.Stringify() to convert the object into string but the methods I have tried, so far have not worked. Any help is appreciated :)

Upvotes: 3

Views: 541

Answers (2)

ggorlen
ggorlen

Reputation: 57135

Almost certainly, based on your error, createdAt is an object with the structure

{_seconds: 123, _nanoseconds: 456}

Change the line

<Typography variant="body1" color="main">{createdAt}</Typography>

to

<Typography variant="body1" color="main">
  {`${createdAt._seconds}:${createdAt._nanoseconds}`}
</Typography>

This explicitly pulls the data out of the object and interpolates it into a template string, avoiding the Objects are not valid as a React child issue.

Here's a minimal reproduction of the error:

class Foo extends React.Component {
  createdAt = {_seconds: 123, _nanoseconds: 456};
  
  render() {
    return <div>{this.createdAt}</div>;
  }
}

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<Foo />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

and the fix:

class Foo extends React.Component {
  createdAt = {_seconds: 123, _nanoseconds: 456};

  render() {
    return (
      <div>
        {`${this.createdAt._seconds}:${this.createdAt._nanoseconds}`}
      </div>
    );
  }
}

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<Foo />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

Upvotes: 1

Chris Chen
Chris Chen

Reputation: 1293

Following ggorlen's comment, What's the response with the following update?

 class Scream extends Component {
    render() {
        const {classes, scream } = this.props;
        const {meme,translation,userImage,userHandle,createdAt,screamId,likeCount,commentCount} = scream;
        return (
            <Card>
                <CardMedia
                image={userImage}
                title="Profile Image"/>
                <CardContent>
                    <Typography variant="h5">{JSON.stringify(userHandle)}</Typography>
                    <Typography variant="body1" color="main">{JSON.stringify(createdAt)}</Typography>
                    <Typography variant="body2">{JSON.stringify(meme)}</Typography>
                    <Typography variant="body2">{JSON.stringify(translation)}</Typography>
                </CardContent>
            </Card>  
        )
    }
}

Upvotes: 1

Related Questions