3

尝试将父数据传递给子组件时,我一直碰壁。

我的观点:

<%= react_component 'Items', { data: @items } %>

我的Items组件进行 ajax 调用、设置状态并呈现Item. 忽略传递给映射函数key={this.props.id}Item实例,以便组件 html 呈现到页面。但是添加密钥,我得到一个控制台错误:Uncaught TypeError: Cannot read property 'id' of undefined

这是“项目”:

var Items = React.createClass({
    loadItemsFromServer: 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)
        });
    },
    componentDidMount: function() {
        this.loadItemsFromServer();
    },
    render: function() {
        var itemNodes = this.props.data.map(function() {
            return (
                <Item key={this.props.id} />
            );
        });
        return (
            <div className="ui four column doubling stackable grid">
                {itemNodes}
            </div>
        );
    }
});

我的 item.js.jsx 组件只是格式化每个Item

var Item = React.createClass({
    render: function() {
        return (
            <div className="item-card">
                <div className="image">

                </div>
                <div className="description">
                    <div className="artist">{this.props.artist}</div>
                </div>
            </div>
        );
    }
});

React 开发工具扩展显示了 Items 中的 props 和 state 数据。然而,孩子们是空的。

在此处输入图像描述

我知道这一点,但我正在使用this.props.id. 我不确定我错过了什么?

4

2 回答 2

1

Items我在组件中发现您发布的代码存在一些问题

  1. 您正在渲染this.props.data,而实际上this.state.data是使用 ajax 请求更新的渲染。您需要渲染this.state.data但从中获取初始值props
  2. map 迭代器函数接受一个表示当前数组元素的参数,使用它来访问属性而不是使用未定义的 this

更新后的代码应如下所示

var Item = React.createClass({
    render: function() {
        return (
            <div className="item-card">
                <div className="image">

                </div>
                <div className="description">
                    <div className="artist">{this.props.artist}</div>
                </div>
            </div>
        );
    }
});

var Items = React.createClass({
    getInitialState: function() {
        return {
            // for initial state use the array passed as props,
            // or empty array if not passed
            data: this.props.data || []
        };
    },
    loadItemsFromServer: function() {
        var data = [{
            id: 1,
            artist: 'abc'
        }, {
            id: 2,
            artist: 'def'
        }]
        this.setState({
            data: data
        });

    },
    componentDidMount: function() {
        this.loadItemsFromServer();
    },
    render: function() {
        // use this.state.data not this.props.data, 
        // since you are updating the state with the result of the ajax request, 
        // you're not updating the props
        var itemNodes = this.state.data.map(function(item) {
            // the map iterator  function takes an item as a parameter, 
            // which is the current element of the array (this.state.data), 
            // use (item) to access properties, not (this)

            return (
                // use key as item id, and pass all the item properties 
                // to the Item component with ES6 object spread syntax
                <Item key={item.id} {...item} />
            );
        });
        return (
            <div className="ui four column doubling stackable grid">
                {itemNodes}
            </div>
        );
    }
});

这是一个工作示例http://codepen.io/Gaafar/pen/EyyGPR?editors=0010

于 2016-06-17T00:36:59.227 回答
0

您的实施存在一些问题。

首先,你需要决定:你想从你的视图中渲染传递给 Items 组件的@items 吗?或者你想异步加载它们?因为现在我得到的印象是你试图同时做这两个......

渲染从视图传递的项目

如果您想渲染传递给组件的视图中的项目,请确保它是正确的 json。您可能需要在其上调用“as_json”。

<%= react_component 'Items', { data: @items.as_json } %>

然后,在您的组件中,映射项目以呈现<Item />组件。这是第二个问题,关于您的密钥。您需要将 item 变量定义为 map 函数的回调函数,并从中读取 id:

var itemNodes = this.props.data.map(function(item) {
  return (
    <Item key={item.id} artist={item.artist} />
  );
});

请注意,我还将作者添加为道具,因为您在<Item />组件中使用它。

您可以删除您的componentDidMountloadItemsFromServer功能,因为您没有使用它们。

异步加载项目

如果你想异步加载项目,就像你试图在你的loadItemsFromServer函数中做的那样,首先,从你的视图中传递 url 并删除 {data: @items} 部分,因为你将从你的组件中加载项目,就像是:

<%= react_component 'Items', { url: items_path(format: :json) } %>

如果要呈现异步获取的项目,请使用:

var itemNodes = this.state.data.map(function(item) {
  return (
    <Item key={item.id} artist={item.artist} />
  );loadItemsFromServer
});

注意我this.props.map改为this.state.map

您现在可以使用您的 componentDidMount 和 loadItemsFromServer 函数来加载数据并将它们保存到状态。

于 2016-06-16T13:43:38.480 回答