johncho johncho - 7 months ago 17
Javascript Question

Iterating through a JSON response in JSX Render for React.js

I'm trying to create a table from a JSON response formulated from a submitted form, therefore the initial render needs to be blank, but this blank state is proving to be an issue.

The issue is complicated further by the fact that the response could have different headers, number of columns, and order.

Parent component



This gets the resultData and passes it to a child component

<ReportsTable title={this.props.title} resultData={this.state.resultData} />


Child component



var ReportsTable = React.createClass({
render: function() {
var resultData = this.props.resultData;

return(
<div>
<h3>{this.props.title}</h3>
<table>
<tr>
//iteration here
</tr>
</table>
</div>
)

}
});


Any attempt at iteration gives me a

Uncaught TypeError: Cannot read property XXX of undefined




The Data received is in this type of format

[Array[1], Array[1]]
0: Array[1]
0: Object
family_name: "Sales"
gross_margin: "0%"
net_profit: "$0.00"
profit_percent: "0%"
quantity_on_hand: 2863
retail: "$9,347.12"
total_cost: "$7,615.96"
total_sold: 49
1: Array[1]
0: Object
family_name: "Service"
gross_margin: "0%"
net_profit: "$0.00"
profit_percent: "0%"
quantity_on_hand: 147.5
retail: "$939.05"
total_cost: "$268.40"
total_sold: 10.8





[UPDATE]



So we modified the response from the server so that I get one less nest in the Array. But now when I try
resultData.map(function(item) { })
and I get an "Uncaught TypeError: undefined is not a function" error as I'm trying to map through the properties of the Object. When I try to map through an Array it works so I don't think it's my syntax.

In the end, my trouble is iterating through the properties of each Object.

This part from the parent works



{resultData.map(function(tableRow, i) {
return (
<TableRow tableRow={tableRow} key={i} />
);
})}


This part in the Child Component does not



var TableRow = React.createClass({
render: function(){
var tableRow = this.props.tableRow;
console.log(tableRow);

return(
<tr key={tableRow}>
{tableRow.map(function(tableItem, i){
<td key={i}>{tableItem}</td>
})}
</tr>
);
}
});

Answer

So this works

<table className="table table-condensed table-striped">
    <thead>
        <tr>
            {resultTitles.map(function(title){
                var textAlignLeft = false;
                if(textLeftMatch.test(title)){
                     textAlignLeft = true;
                }
                title = title.replace(/_/g, " ");

                return <th key={title} className={textAlignLeft ? 'text-left' : ''}>{title}</th>
            })}
        </tr>
    </thead>
    <tbody>
        {resultData.map(function(tableRow, i) {
            return (
                <TableRow tableRow={tableRow} key={i} />
            );
        })}
    </tbody>
</table>

var TableRow = React.createClass({
    render: function(){
        var tableRow = this.props.tableRow;
        var rowArray = $.map(tableRow, function(value, index){
           return [value];
        });

        return(
                <tr key={tableRow}>
                    {rowArray.map(function(tableItem, i){
                        return <td key={i} className={(i === 0) ? 'text-left' : ''}>{tableItem}</td>
                    })}
                </tr>
        );
    }
});

However, after searching for awhile, I found a better starting point found here http://dynamictyped.github.io/Griddle/quickstart.html