我试图构建一个小的React.js应用程序,我的组件结构如下所示:
MainComponent - CategoryList -Category - ItemsList -Item
我的MainContent组件对其的状态数据执行ajax请求,该请求componentDidRender:返回此对象:
componentDidRender:
data:[ Object[0] -name -items[] , Object[1], Object[2] ]
现在,我希望我的CategoryList通过名称写出所有类别,效果很好,但我也想打印出所选类别的项目。这是我的ItemsList组件:
var ItemsList = React.createClass({ render:function(){ var itemNodes = this.props.category.items.map(function(item){ return ( <Item name={item.name} /> ); }); return( <div className="itemList"> {itemNodes} </div> ); } });
这就是我从父组件传递“类别”属性的方式
<ItemsList category={this.state.data[0]} />
我收到一个错误消息:“无法读取未定义的属性项目”,这意味着从未分配类别道具。我知道this.state.data包含对象数组,因此在这里看不到错误。
我做错了什么?
编辑:每个请求,这是我的MainComponent:
var MainComponent = React.createClass({ getInitialState:function(){ return {data: []}; }, componentDidMount:function(){ $.ajax({ type:'get', url: '/categories', dataType: 'json', success:function(data){ this.setState({data: data}); }.bind(this) }); }, render: function(){ return ( <div className="row"> <div className="col-md-6"> <CategoryList categories={this.state.data} /> </div> <div className="col-md-6"> <ItemsList category={this.state.data[0]} /> </div> </div> ); } });
您的主要组件使用中的空数组初始化状态data。渲染将始终失败,因为没有this.state.data[0]。
data
this.state.data[0]
可能有人会回答ajax请求将提供此state属性的值data(假设您的Web服务正在提供有效的数组)。 但是 ,这仅在从服务器接收到响应之后发生,而在第一次渲染后不会发生。
如果信息立即可用,则可以使用setState方法componentWillMount或组件构造函数,以免触发第二次渲染:
setState
componentWillMount
在挂载发生之前立即调用componentWillMount()。在render()之前调用它,因此在此方法中同步设置状态不会触发重新渲染。避免在此方法中引入任何副作用或订阅。
在这种情况下,由于我们正在等待远程信息,因此React文档仍然建议使用componentDidMount,以及在此处使用的方法:
componentDidMount
挂载组件后立即调用componentDidMount()。需要DOM节点的初始化应该在这里进行。如果需要从远程端点加载数据,这是实例化网络请求的好地方。在此方法中设置状态将触发重新渲染。
因此,组件的render方法必须能够处理丢失的状态变量。有多种方法可以解决此问题,但是data最简单的方法是阻止嵌套元素被渲染直到我们拥有为止。使用某些附加逻辑,应用程序可以通知用户特定组件正在加载。
render() { return ( <div className="row"> <div className="col-md-6"> <CategoryList categories={this.state.data} /> </div> <div className="col-md-6"> {this.state.data.length > 0 && <ItemsList category={this.state.data[0]} /> } </div> </div> ); }