How to iterate through a list of objects in reactjs using map function?

8.4k views Asked by At

I am trying to iterate through an array of objects in reactjs but facing issue. The array basically consists of objects where each object is a row in a table.

Example -

A table like this
| A | B | C |
| 1 | 2 | 3 |
| 4 | 5 | 6 |

would be represented using the following array
[
  {"A": 1, "B": 2, "C": 3},
  {"A": 4, "B": 5, "C": 6}
]

I am trying to loop through the values using the following syntax -

this.state.data.map(item =>
  Object.entries(item).map(([key, value]) =>
    <Column field={key} header={key}>{value}</Column>
  ))

But this gives me the desired table concatenated multiple times. I know there's some issue with the looping but not getting exactly where the difficulty is.

Similar case in python would look like -

for item in array:
    for key, value in item.items():
        # create a row
2

There are 2 answers

2
Kevin Moe Myint Myat On BEST ANSWER

You should consider realigning your way of rendering.

I guess first to get the thead header of your table which can be done by

    <thead>
    {Object.keys(this.state.data[0]).map((v) => 
     <th>{v}</th>)
    }
    </thead>

Then after that is the tbody which can be done by

<tbody>
   {this.state.data.map((v) => 
    <tr>
    {Object.values(v).map((value) => <td>{value}</td>}
    </tr>)
    }
</tbody>

Reference: https://reactjs.org/docs/thinking-in-react.html

EDIT: You can replace my example of thead, tbody, tr, td with Grid,TableHead,TableBody, Row, Column whichever library components of yours but you get the idea.

0
T.J. Crowder On

Assuming a Row component, you'd return a Row for each callback of the outer map, something like this (I've put them in a hypothetical Container just for context):

<Container>
{this.state.data.amp((item, index) =>
    <Row key={index}>
    {Object.entries(item).map(([key, value]) =>
        <Column field={key} header={key} key={key}>{value}</Column>
    )}
    </Row>
)}
</Container>

Note I've added the key property, since these are arrays. (Using the index for the key on Row is less than ideal. If the item objects have some unique property you could use instead, that would be better. Using an index is fine if the array never changes during the component lifecycle, but if it does, it can lead to bad renders. More about that in the React documentation.)

But, using Object.entries on item is less than ideal, because it relies on the order of the properties in item, and although JavaScript objects do provide an order for their properties, relying on that order is generally not best practice because the order isn't as simple as it seems and it's really easy to build what seems like the same object but with the properties in a different order.¹ Instead, I suggest having an array of the property names in the order you want them to appear in the columns, and then using that array:

<Container>
{this.state.data.amp((item, index) =>
    <Row key={index}>
    {propertyNamesInColumnOrder.map(key =>
        <Column field={key} header={key} key={key}>{item[key]}</Column>
    )}
    </Row>
)}
</Container>

¹ "it's really easy to build what seems like the same object but with the properties in a different order" For example:

const obj1 = {a: 1, b: 2};
const obj2 = {b: 2, a: 1};

Those look like the same object. They both have a and b properties, and the property values are the same. But the properties are in a different order: obj1's properties are in the order a, b, but obj2's properties are in the order b, a.

But wait, it gets worse:

const obj3 = {"1": "one", "0": "zero"};
const obj4 = {"0": "zero", "1": "one"};

Surely, if obj1 and obj2's properties aren't in the same order, then obj3 and obj4's properties aren't in the same order, right?

Wrong.

They're in the same order, because properties whose names are what the spec calls "array indexes" (canonical numeric Strings whose numeric value is either +0 or a positive integral Number ≤ 232 - 1) are always in numeric order.

Then you throw inherited properties in, and it gets worse still. So again, in general, avoid relying on object property order.