Extract TableBody Render Error:

Hi everyone, wondering if I could get some support. Following Lessons 20 and 21 - Extract TableBody & Rendering Cell Content, I run into the error:

Uncaught Error: Objects are not valid as a React child (found: object with keys {_id, name}). If you meant to render a collection of children, use an array instead.

This occurs when I’ve extracted the TableBody code to another external file, and then comment out the old TableBody code in movieTable.jsx.

I’ve traced it back to the declaration of TableBody component within moviesTable.jsx. When I comment the new <TableBody columns={this.columns} data={movies} /> line out and leave the unextracted code within moviesTable it works.

Here is my code below:

moviesTable.jsx

render() {
    const { movies, onDelete, onLike, sortColumn, onSort } = this.props;

    return (
      <table className="table">
        <TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort} />
        <TableBody columns={this.columns} data={movies} />
        {movies.map((movie) => (
          <tr key={movie._id}>
            <td>{movie.title}</td>
            <td>{movie.genre.name}</td>
            <td>{movie.numberInStock}</td>
            <td>{movie.dailyRentalRate}</td>
            <td>
              <Like liked={movie.liked} onClick={() => onLike(movie)} />
            </td>
            <td>
              <button onClick={() => onDelete(movie)} className="btn btn-danger btn-sm">
                Delete
              </button>
            </td>
          </tr>
        ))}
      </table>
    );
  }


tableBody.jsx

import React, { Component } from 'react';
import _ from 'lodash';

class TableBody extends Component {
  render() {
    const { data, columns } = this.props;
    return (
      <tbody>
        {data.map((item) => (
          <tr>
            {columns.map((column) => (
              <td>{_.get(item, column.path)}</td>
            ))}
          </tr>
        ))}
      </tbody>
    );
  }
}

export default TableBody;

Is anybody able to assist me on this? Thanks very much!

There is nothing wrong with the code. You will need to share the value of columns variable.

Note: that error (Objects are not valid as React child…) means you are probably trying to display an object into the element instead of it’s property.
Use console.log(variable) to see what you are getting. And let me know if it helps or not.

Thanks

Thanks for your response. Trying to understand your feedback, I thought the columns value was being passed in tableBody when we call the lodash method in columns.map(column => ( <td>{_.get(item, column.path)}</td> ))? How do I modify the lodash method such that I’m getting the columns value?

PS - I did a console.log(data, columns) and the below screenshot is my output. Obviously since I can see the data being pulled in, I’m sure like you say I’m displaying the actual object instead of the property, I just don’t know how to fix it…

Can you push the code to a public Git repository and share me the link (I will need to pull into my pc and execute it to see the problem)?
I will look into it and reply here with the fix as well as tell you what was the problem.

Thank you so much. I’ve pushed to a public repo here. GitHub - Hechen93/vidly

_.get(object, 'property');

is same as:

object.property

except _.get() will also try to get nested values.

here is your data:

{_id: '5b21ca3eeb7f6fbccd47181e', title: 'Gone Girl', numberInStock: 7, dailyRentalRate: 4.5, genre: {_id: '5b21ca3eeb7f6fbccd471820', name: 'Thriller'}

Here is what happens when you do:

_.get(item, column.path)

in the loop:

First,
you will receive the path: title
now, _.get() will extract the value of object.title (output: Gone Girl).
Similarly, other values will also be extracted except genre (which is an object).
And, since I mentioned _.get() can extract nested object property values as well, we need to get the genre.name for Genre.

And this is where you made a tiny mistake in your code.

The variable: columns should have a path: genre.name not just genre.

Replace:

{ path: 'genre', label: 'Genre' }

With

{ path: 'genre.name', label: 'Genre' }

in the moviesTable.jsx file’s column variable and your code will work.

One another info for you: if you are receiving the warning ‘child elements should have a unique key…’, then consider using key={Math.random()} utility function instead of creating a key.
Well, this is just a temporary fix and if you connect your ReactJS app to real back end (like MongoDB), then you will have access to unique key as permanent fix.

Hope this helps.

Thanks so much for your help!

1 Like