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

21,446

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>
Share:
21,446
Luke Sharon
Author by

Luke Sharon

Updated on April 12, 2021

Comments

  • Luke Sharon
    Luke Sharon about 3 years

    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?

    • SpiritOfDragon
      SpiritOfDragon almost 4 years
      what is your object structure? try outputting the name or other display property <tr key={item.id}>{item.name}</tr>
    • Akshay
      Akshay almost 4 years
      When mapping array of objects, each object is passed to the item. To access the content of the object, you can use item.property where property is the property youwant to access. In your case I think it would be something like <tr key={item.OrderID}>{item.Quantity}</tr> <- This will print each row with the quantity property and OrderID as key.
    • HMR
      HMR almost 4 years
      Try to do: <tr key={item.id}><OrderRow order={item} /></tr> and create an Order component: function Order({order})=><><td>{order.name}...other columns</>
    • Alex L
      Alex L almost 4 years
      Take a look at my answer it should do the trick - stackoverflow.com/a/61557412/9792594 - would be great if you could provide your state (array of objects), I had to guess.
  • Luke Sharon
    Luke Sharon almost 4 years
    I made this adjustment. The error goes away, but no table renders on the page. Any suggestions?
  • Luke Sharon
    Luke Sharon almost 4 years
    I made this adjustment. The error goes away, but no table renders on the page. Any suggestions?
  • Sohan Patil
    Sohan Patil almost 4 years
    First please check what you are getting in this.state.orderDetails
  • Luke Sharon
    Luke Sharon almost 4 years
    I am getting an array with two objects.