Dynamically create data table in ReactJS

12,933

You can group your data by header with Array.prototype.reduce() and then create appropriate elements:

render: function() {

    var tableElements = this.state.data.reduce(function(grouped, item) {
        if (item.element == "th") {
            grouped.push({
                header: item,
                rows: []
            });
        } else {
            grouped[grouped.length - 1].rows.push(item);
        }
        return grouped;
    }, []).reduce(function(elements, item) {
        elements.push(<thead>
                          <tr>
                              <ThElement width="280" data={item.header.description}/>
                              <ThElement width="150" data={item.header.L1}/>
                          </tr>
                      </thead>);
        elements.push(<tbody>
                      {
                          item.rows.map(function(row) {
                              return (<tr>
                                          <TdElement data={row.description}/>
                                          <TdElement data={row.L1}/>
                                      </tr>);
                          });
                      }
                      </tbody>);
        return elements;

    }, []);

    return (
        <div>
            <table id="measurementsDataTable" className="row-border compact">
            { tableElements }
            </table>
        </div>
    );
}
Share:
12,933
Jan
Author by

Jan

Updated on June 04, 2022

Comments

  • Jan
    Jan almost 2 years

    I have problem with creating dynamic data table in ReactJs. In state.data I get my data which I loop to create data table.

    Here is my render function:

    render: function() {
            return (
                <div>
                    <table id="measurementsDataTable" className="row-border compact">
                        {
                            this.state.data.map(function(item) {
                                if( item.element == "th" ){
                                    return (
                                        <thead>
                                            <tr>
                                                <ThElement width="280" data={item.description}/>
                                                <ThElement width="150" data={item.L1}/>
                                            </tr>
                                        </thead>
                                    )
                                }
                                else if ( item.element == "tr" ) {
                                    return (
                                        <tbody>
                                            <tr>
                                                <TdElement data={item.description}/>
                                                <TdElement data={item.L1}/>
                                            </tr>
                                        </tbody>
                                    )
                                }
                            })
                        }
    
                    </table>
                </div>
            );
        }

    The problem is the element "tbody" which is given to the every single "tr" row. And it should be just in first "tr" to last "tr".

    This would't be a problem if I could just return start of "tbody", but react doesn't allow that.

    Is there any elegant solution to that?

    Edit: Currently is HTML looking like this. All the difference is in the "tbody" element.

    <table>
    <thead>
        <tr>
            <th>Phase</td>
            <th>L1</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Voltage</td>
            <td>224.2</td>
        </tr>
    </tbody>
    <tbody>
        <tr>
            <td>Current</td>
            <td>0.00 mA</td>
        </tr>
    </tbody>    
    <thead>
        <tr>
            <th>Phase 2</td>
            <th>L2</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Voltage2</td>
            <td>223.2</td>
        </tr>
    </tbody>
    <tbody>
        <tr>
            <td>Current2</td>
            <td>0.00 mA</td>
        </tr>
    </tbody>
    

    and It should looking like this:

    <table>
    <thead>
        <tr>
            <th>Phase</td>
            <th>L1</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Voltage</td>
            <td>224.2</td>
        </tr>
        <tr>
            <td>Current</td>
            <td>0.00 mA</td>
        </tr>
    </tbody>    
    <thead>
        <tr>
            <th>Phase 2</td>
            <th>L2</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Voltage2</td>
            <td>223.2</td>
        </tr>
        <tr>
            <td>Current2</td>
            <td>0.00 mA</td>
        </tr>
    </tbody>