4

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>
        );
    }
});
8
  • Can you post what the actual data looks like? And the call that receives this datsa? Commented Mar 12, 2015 at 19:49
  • Sure, just added a typical response. I can display the response without any formatting just fine, it's the formatting that's troubling me. Commented Mar 12, 2015 at 19:56
  • 1
    So, resultData.map(function(item) { }) throws an error? Commented Mar 12, 2015 at 19:58
  • 1
    Trying it now, and tomorrow morning. It's giving me the top layer, and not exactly what I need, but I think I can nest these to get to what I need. Thank you. I'll write back when I have an answer. Commented Mar 12, 2015 at 20:26
  • 1
    You have doubly-nested arrays, so your iteration is probably wrong. That is the crux of your question and issue, so I'm confused why you didn't post the iteration code. Update the question, and it will probably be obvious what the issue is. Commented Mar 13, 2015 at 5:21

3 Answers 3

3

I have had the same problem.

The reason why i got "Uncaught TypeError: undefined is not a function" was because i tried to iterate over the properties of a json object using map which is not possible. The solution for me was to iterate over the keys of the json object using Object.keys(). See below for my solution.

    Data: 
    {
        "status": {
            "build": {
                "a":"b",
                "c":"d"
            }
        }
    }   
       `render: function(){
            var buildInfo = this.props.applicationInfo.status.build;
            var properties = Object.keys(buildInfo).map((k, idx) => {
               return (
                 <p key={idx}><strong>{k}</strong> - {buildInfo[k]}</p>
               );
            });
            return(
                <div>
                    {properties}
                </div>
            );
        }`
Sign up to request clarification or add additional context in comments.

Comments

1

If you have JSON instead of Array and you want to loop in JSX react render function use Object.keys:

  <select className="form-control" >
   {Object.keys(item.unit).map(unit => {
      return <option value="1">1</option>
   })}
  </select>

Comments

0

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

3 Comments

While this answer is probably correct and useful, it is preferred if you include some explanation along with it to explain how it helps to solve the problem. This becomes especially useful in the future, if there is a change (possibly unrelated) that causes it to stop working and users need to understand how it once worked.
You're right, I'll do a write up this week and keep this in mind for the future.
The comment by @KevinBrown makes more sense now that the link is not working anymore and I stuck with the same problem :(

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.