'create table from JSON object in react

I am creating a table dynamically in React with the API response as it is as it receives.

data = {"name":"tom", "age":23, "group":null, "phone":xxx}

It is working fine with that, but the group key sometimes contains another object, so I want to create a sub-table whenever there is another object inside a key.

For example:

data = {"name":"tom", "age":23, "group":{"id":123, "joined_at":12-jan-2022}, "phone":xxx}

My current code is:

<table>
  {Object.keys(data).map(index=> (
    <tr>
      <td>{index}</td>
      <td>{data[index]?.toString()}</td>
    </tr>
   ))}
</table>


Solution 1:[1]

The code you have shared would change as follows:

<table>
    {Object.keys(data).map((item, index) => {
        if (group) {
            return (
                <>
                    <tr>
                        <td>{index}</td>
                        <td>{item.toString()}</td>
                    </tr>
                    <tr>
                        <table>
                            <tr>
                                <td>{group.id}</td>
                                <td>{group.joined_at}</td>
                            </tr>
                        </table>
                    </tr>
                </>
            );
        }
        return (
            <tr>
                <td>{index}</td>
                <td>{item.toString()}</td>
            </tr>
        );
    })}
</table>;

You can fix the formatting as per your needs but this is essentially how you would create a sub-table based on the value of group

A slightly improved version would be :

const normalTableRow = (index, item) => {
    return (
        <tr>
            <td>{index}</td>
            <td>{item.toString()}</td>
        </tr>
    );
};

<table>
    {Object.keys(data).map((item, index) => {
        if (group) {
            return (
                <>
                    {normalTableRow(index, item)}
                    <tr>
                        <table>
                            <tr>
                                <td>{group.id}</td>
                                <td>{group.joined_at}</td>
                            </tr>
                        </table>
                    </tr>
                </>
            );
        }
        return normalTableRow(index, item);
    })}
</table>;

EDIT: updating solution based on comment

 const normalTableRow = (index, item) => {
    return (
        <tr>
            <td>{index}</td>
            <td>{item.toString()}</td>
        </tr>
    );
};

const isObject = (value) => {
    return typeof value === 'object' && !Array.isArray(value) && value !== null;
};

<table>
    {Object.keys(data).map((item, index) => {
        let subTables = Object.keys(item).map((key) => {
            if (isObject(item[key])) {
                return (
                    <tr>
                        <table>
                            <tr>
                                {Object.keys(item[key]).map((subKey) => {
                                    return <td>{item[key][subKey]}</td>;
                                })}
                            </tr>
                        </table>
                    </tr>
                );
            }
        });

        return (
            <>
                {normalTableRow(index, item)}
                {[...subTables]}
            </>
        );
    })}
</table>;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1