Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display an array of objects in a table in react

I have recently been learning react. I set my state to an array of objects. I want to display that array in a table on the page (each object on one line). I have been researching map, however I'm having a bit of trouble understanding it. I was able to use map just fine at a different place in my code to map through an array, but I am having trouble mapping through an array of objects. This code takes place in the div inside my render:

<table>
  {this.state.orderDetails.map((item =>
  <tr key={item}>{item}</tr>
  ))}
</table>

I am getting this error: 'Unhandled Rejection (Error): Objects are not valid as a React child (found: object with keys {OrderID, CustomerID, AddressID, Date, ItemID, BookID, UnitPrice, Quantity}). If you meant to render a collection of children, use an array instead.'

Order details has definitely been set correctly; when I open my react tools and check the state in this component, it is listed as an array with two elements, each element being an object with multiple elements within. How can I successfully map through this array of objects and display it in table form (with each object on its own row)? Thanks is advance for any ideas!!!

EDIT After taking some advice from the answers and comments, I have changed my map to the following:

<table>
  {this.state.orderDetails.map((item =>
  <tr><td key={item.OrderID}>{item.CustomerID}</td></tr>
  ))}
</table>

The error has gone away. However, when I click the button, I get one tiny table cell that is empty. I would expect multiple cells since my array has two objects, and of course I would expect it not to be empty. Also, I am wanting to display more than just customerID. I have several elements in each object that I want to render on the table (ex. quantity, price, title, etc...). Any further sugesstions?

like image 404
Luke Sharon Avatar asked Sep 05 '25 04:09

Luke Sharon


1 Answers

We don't know what your array of objects look like so we have to guess:

So I guess this input:

const initState = [
    { id: 1, name: "bread", quantitiy: 50 },
    { id: 2, name: "milk", quantitiy: 20 },
    { id: 3, name: "water", quantitiy: 10 }
  ];

And I get this output:

enter image description here

It's completely flexible so if we have input:

const initState = [
    { id: 1, name: "bread", quantitiy: 50, location: "cupboard" },
    { id: 2, name: "milk", quantitiy: 20, location: "fridge" },
    { id: 3, name: "water", quantitiy: 10, location: "fridge" }
  ];

Then we get this output:

enter image description here

The most important thing is to map over the object values inside the map which maps over the state array:

{state.map((item) => (
        <tr key={item.id}>
          {Object.values(item).map((val) => (
            <td>{val}</td>
          ))}
        </tr>
      ))}

full demo below and on codePen: https://codepen.io/Alexander9111/pen/zYvEbML

I used a functional component but it would be very similar with a class-based component.

NOTE: you could also create a row component and then call that component inside the map over the state array. Inside this row component, you would map of the Object keys like I did and output table data elements. It's a balance between death by component (i.e. breaking down everything into smaller and smaller components nested inside each other) and fewer components which are too complex.

function MyTable() {
  const initState = [
    { id: 1, name: "bread", quantitiy: 50, location: "cupboard" },
    { id: 2, name: "milk", quantitiy: 20, location: "fridge" },
    { id: 3, name: "water", quantitiy: 10, location: "fridge" }
  ];
  const [state, setState] = React.useState(initState);

  return (
    <table>
      <tr key={"header"}>
        {Object.keys(state[0]).map((key) => (
          <th>{key}</th>
        ))}
      </tr>
      {state.map((item) => (
        <tr key={item.id}>
          {Object.values(item).map((val) => (
            <td>{val}</td>
          ))}
        </tr>
      ))}
    </table>
  );
}

ReactDOM.render(<MyTable />, document.getElementById("target"));
th,
td {
  border: 1px solid black;
  margin: 0px 0px;
  padding: 5px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="target"></div>
like image 156
Alex L Avatar answered Sep 07 '25 17:09

Alex L