通过具有已知键名的道具访问数据会对js产生反应

时间:2015-06-17 13:49:42

标签: javascript json reactjs

刚开始学习React JS,我已经打了一个砖墙。

我目前有两个组件(可能是错误的方法)。

  • LootBox
    • LootTable

LootBox通过ajax调用json文件,LootTable需要访问这些数据。

这是我目前的代码。

var LootBox = React.createClass({
                loadLootFromServer: function() {
                    $.ajax({
                      url: this.props.url,
                      dataType: 'json',
                      cache: false,
                      success: function(data) {
                        this.setState({
                            data: data
                        });
                      }.bind(this),
                      error: function(xhr, status, err) {
                        console.error(this.props.url, status, err.toString());
                      }.bind(this)
                    });
                },
                getInitialState: function() {
                    return {data: []};
                },
                componentDidMount: function() {
                    this.loadLootFromServer();
                },
                render: function () {
                    return (
                        <LootTable data={this.state.data} />
                    )
                } 
            });

LootTable

var LootTable = React.createClass({

                render: function () {
                    return (
                        <div className="table-responsive">
                            <table className="table table-bordered table-hover">
                                <tr>
                                    <th>Head <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Neck <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td>{this.props.data.head.id}</td>
                                    <td>{this.props.data.neck.id}</td>
                                </tr>
                                <tr>
                                    <th>Shoulder <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Chest <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                                <tr>
                                    <th>Waist <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Legs <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                                <tr>
                                    <th>Feet <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Wrist <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                                <tr>
                                    <th>Gloves <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Back <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                                <tr>
                                    <th>Ring 1 <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Ring 2 <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                                <tr>
                                    <th>Trinket 1 <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Trinket 2 <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                                <tr>
                                    <th>Main Hand <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                    <th>Off Hand <span className="glyphicon glyphicon-th-list pull-right"></span></th>
                                </tr>
                                <tr>
                                    <td></td>
                                    <td></td>
                                </tr>
                            </table>
                        </div>
                    )
                }
            });

渲染

React.render(
                <LootBox url="http://127.0.0.1:3001/loot.json" />,
                document.getElementById('content')
            );

JSON

[
    {
      "main_hand": {
        "id": 113937,
        "bonus": "449"
      },
      "off_hand": {
        "id": 113960,
        "bonus": "449"
      },
      "head": {
        "id": 119321,
        "bonus": "449"
      },
      "neck": {
        "id": 113890,
        "bonus": "449"
      },
      "shoulders": {
        "id": 119322,
        "bonus": "449"
      },
      "back": {
        "id": 113878,
        "bonus": "449"
      },
      "chest": {
        "id": null,
        "bonus": "None"
      },
      "wrist": {
        "id": 113935,
        "bonus": "449"
      },
      "hands": {
        "id": 119319,
        "bonus": "449"
      },
      "waist": {
        "id": 113964,
        "bonus": "449"
      },
      "legs": {
        "id": 119320,
        "bonus": "449"
      },
      "feet": {
        "id": 113895,
        "bonus": "449"
      },
      "finger1": {
        "id": 113901,
        "bonus": "449"
      },
      "finger2": {
        "id": null,
        "bonus": "None"
      },
      "trinket1": {
        "id": 113889,
        "bonus": "449"
      },
      "trinket2": {
        "id": 113986,
        "bonus": "449"
      }
    }
]

我不完全确定我做错了什么,因为在尝试访问LootBox上的道具时(例如this.props.data.head.id),我得到了TypeError: undefined is not an object (evaluating 'this.props.data.head.id')

有人有什么理论吗?

编辑:将console.log添加到成功函数后,我将返回此内容。

[Log] [ (loot, line 10)
Object
back: Object
bonus: "449"
id: 113878
__proto__: Object
chest: Object
feet: Object
finger1: Object
finger2: Object
hands: Object
head: Object
legs: Object
main_hand: Object
neck: Object
off_hand: Object
shoulders: Object
trinket1: Object
trinket2: Object
waist: Object
wrist: Object
__proto__: Object
]

3 个答案:

答案 0 :(得分:1)

你得到这个TypeError的原因是因为你在LootBox组件上的data的初始状态是一个空数组。这会在初始渲染时传递给LootTable。这意味着LootTable的初始渲染上的this.props.data是一个空数组,并且它试图访问空数组上的head键并且无法执行此操作,从而导致TypeError。

可能的解决方案是在尝试访问其密钥之前检查空数组。像这样:

var LootTable = React.createClass({
    render: function () {
    var headID = this.props.data.head.id == null ? "Default value" : this.props.data.head.id;
    var neckID = this.props.data.neck.is == null ? "Default value" : this.props.data.neck.id;
        return (
            <snip>
        )
    }
});

然后你只需使用创建的变量而不是JSX中的props。

答案 1 :(得分:-1)

ajax调用是否返回了您发布的数组?

如果是这样,您需要执行this.props.data[0].head.id

答案 2 :(得分:-1)

您的初始渲染(在componentDidMount之前)将不会有任何数据,因此您的LootTable组件将针对空数组工作,这将无效。