1

Im fairly new to React and I have a react function component called DynamicTable. I am passing some json data from an api that looks like this:

const tableData2 = [
    {"RelocationId":1,"AssociateId":"2","StartingLocation":"Jacksonville","EndingLocation":"Macon","PlanningCenter":"Buffalo","CostCenter":"A","OpenDate":"2020-10-20T00:00:00","CloseDate":"2020-10-22T00:00:00","RelocationTypeId":"Full Relocation"},
    {"RelocationId":2,"AssociateId":"2","StartingLocation":"Los Angelos","EndingLocation":"New York","PlanningCenter":"Detroit","CostCenter":"B","OpenDate":"2020-09-20T00:00:00","RelocationTypeId":"Full Relocation"},
    {"RelocationId":3,"AssociateId":"1","StartingLocation":"Washington DC","EndingLocation":"Houston","PlanningCenter":"Dalls","CostCenter":"C","OpenDate":"2020-08-08T00:00:00","CloseDate":"2020-08-15T00:00:00","RelocationTypeId":"Full Relocation"},
    {"RelocationId":4,"AssociateId":"1","StartingLocation":"Lakeland","EndingLocation":"Atlanta","PlanningCenter":"Seattle","CostCenter":"D","OpenDate":"2020-09-12T00:00:00","CloseDate":"2020-09-28T00:00:00","RelocationTypeId":"Full Relocation"},
    {"RelocationId":5,"AssociateId":"1","StartingLocation":"San Diego","EndingLocation":"Woodbury","PlanningCenter":"Baltimore","CostCenter":"E","OpenDate":"2020-10-02T00:00:00","CloseDate":"2020-10-17T00:00:00","RelocationTypeId":"Full Relocation"}
]

I have a renderTableHeader function that calls another function called FindMostProperties that basically looks through each of the above json objects in the array and finds the object with most keys and then in the renderTableHeader it creates the columns:

var indexOfMostProperties;

function renderTableHeader() {
        tableData2.forEach(FindMostProperties);

        let header = Object.keys(tableData2[indexOfMostProperties])
        return header.map((key, index) => {
            return <Table.HeaderCell key={index}>{key.toUpperCase()}</Table.HeaderCell>
        })
    }

function FindMostProperties(item, index) {
        var currentObjectProperties = Object.keys(item).length;

        if(currentObjectProperties > mostProperties) {
            mostProperties = currentObjectProperties;
            indexOfMostProperties = index;
        }
    }

Next I have a function called renderTableData that is supposed to create the rows of the table with the data from the values in the json above:

function renderTableData() {
        return tableData2.map((record, index) => {
            let col = Object.keys(record)
            console.log(col);
            return(
                <Table.Row key={record.RelocationId}>
                    {col.map((val, index) => {
                        return <Table.Cell key={index}>{record[col[index]]}</Table.Cell>
                    })}
                </Table.Row>
            )
        }) 
    }

The code I have above is producing a table that looks like this where the Relocation type for the second object is appearing incorrectly in the CloseDate column:


+--------------+-------------+------------------+----------------+----------------+------------+---------------------+---------------------+------------------+
| RelocationId | AssociateId | StartingLocation | EndingLocation | PlanningCenter | CostCenter |      OpenDate       |      CloseDate      | RelocationTypeId |
+--------------+-------------+------------------+----------------+----------------+------------+---------------------+---------------------+------------------+
|            1 |           2 | Jacksonville     | Macon          | Buffalo        | A          | 2020-10-20T00:00:00 | 2020-10-22T00:00:00 | Full Relocation  |
|            2 |           2 | Los Angelos      | New York       | Detroit        | B          | 2020-09-20T00:00:00 | Full Relocation     |                  |
+--------------+-------------+------------------+----------------+----------------+------------+---------------------+---------------------+------------------+


What I want is this result, where there is a blank result in CloseDate column for the second object and the relocation type is in the correct column:


+--------------+-------------+------------------+----------------+----------------+------------+---------------------+---------------------+------------------+--+
| RelocationId | AssociateId | StartingLocation | EndingLocation | PlanningCenter | CostCenter |      OpenDate       |      CloseDate      | RelocationTypeId |  |
+--------------+-------------+------------------+----------------+----------------+------------+---------------------+---------------------+------------------+--+
|            1 |           2 | Jacksonville     | Macon          | Buffalo        | A          | 2020-10-20T00:00:00 | 2020-10-22T00:00:00 | Full Relocation  |  |
|            2 |           2 | Los Angelos      | New York       | Detroit        | B          | 2020-09-20T00:00:00 |                     | Full Relocation  |  |
+--------------+-------------+------------------+----------------+----------------+------------+---------------------+---------------------+------------------+--+


I am using the following libraries for the react component. The Table component comes from the Semantic UI React library(v 0.88.2) and Im using React (v 16.13.1) and also below is the component calling those above table rendering functions:

import React from 'react';
import { Table } from 'semantic-ui-react':

return(
        <div>
            <Table>
                <div>
                    <Table.Header>
                        <Table.Row>
                            {renderTableHeader()}
                        </Table.Row>
                    </Table.Header>
                    <Table.Body>
                        {renderTableData()}
                    </Table.Body>
                </div>
            </Table>
        </div>
    );
qfjr
  • 53
  • 2
  • 6

1 Answers1

0

When rendering the table data, you are rendering varying numbers of columns. That is, in your renderTableData() function, you are creating a new cell for each property of each object (the quantity of which varies). You should use the keys of the object with the most properties as a constant, and simply return an empty cell for nonexistent properties. Something like the following:

function renderTableData() {
        let col = Object.keys(tableData2[indexOfMostProperties]); // this can be defined before the map
        return tableData2.map((record, index) => {
            console.log(col);
            return(
                <Table.Row key={record.RelocationId}>
                    {col.map((val, index) => {
                        if (record[col[index]]) {
                            // property exists on object
                            return <Table.Cell key={index}>{record[col[index]]}</Table.Cell>
                        } else {
                            // property doesn't exist
                            return <Table.Cell key={index}></Table.Cell>
                        }
                    })}
                </Table.Row>
            )
        }) 
    }

Edit:

A few extra optimizations to consider:

function renderTableData() {
        let col = Object.keys(tableData2[indexOfMostProperties]); // this can be defined before the map
        return tableData2.map(record => {
            console.log(col);
            return(
                <Table.Row key={record.RelocationId}>
                    {col.map((val, index) => {
                        // conditional insertion
                        return <Table.Cell key={index}>{record[val] || ''}</Table.Cell>
                    })}
                </Table.Row>
            )
        }) 
    }
Ryan
  • 364
  • 2
  • 7