开发者问题收集

通过具有已知键名的 props 访问数据 react js

2015-06-17
161

刚开始学习 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>
                    )
                }
            });

Render

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 不是对象(评估“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个回答

您收到此 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。

Michael Parker
2015-06-17

ajax 调用是否像您发布的那样返回数组?

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

Crob
2015-06-17

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

Andrew Ingram
2015-06-17