以下是我尝试过的一小段代码:
var CommentBox = React.createClass({
loadCommentsFromServer: function () {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'GET',
success: function (data) {
this.setState({data: data});
}.bind(this),
error: function (xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this),
cache: false
});
},
getInitialState: function () {
return {data: []};
},
componentDidMount: function () {
this.loadCommentsFromServer();
},
render: function () {
return (
<div className="commentBox">
<MessageBox1 data={this.state.data}/>
</div>
);
}
});
var MessageBox1 = React.createClass({
getInitialState: function() {
alert('MessageBox1 getInitialState');
return {nameWithQualifier: 'Mr. ' + this.props.data.pageName};
},
componentDidMount: function() {
alert('this.props.data: ' + this.props.data);
},
render: function() {
return (<div>
<div>{this.state.nameWithQualifier}</div>
<div> {this.props.data.pageName}</div>
</div>
);
}
});
ReactDOM.render(<CommentBox url="/save/6"/>, document.getElementById('content'));
在CommentBox中,我查询ID为6的对象并将其传递给MessageBox1组件。我想在MessageBox1组件中使这个对象成为一个状态变量。这里的问题是,我无法读取道具变量。 &#34; this.props.data&#34;在MessageBox1组件的getInitialState和ComponentDidMount中未定义。然而,在渲染功能中,我可以看到正确的值。我尝试过几个例子,我可以在getInitialState中读取道具数据。为什么这不会发生?请帮忙。我在控制台中没有任何错误。
答案 0 :(得分:2)
我相信你对反应组件的生命周期感到困惑。
我建议您快速阅读本文,了解何时调用每个生命周期方法。 http://busypeoples.github.io/post/react-component-lifecycle/
在你的getInitialState方法的messagebox1中,初始化你的状态结构,以防止在道具可用之前访问道具。
{ nameWithQualifier: '' }
您正在调用异步操作来获取数据,因此无法保证何时将检索数据。但是,根据你现在的方式(在componentDidMount上),它将始终在messageBox1初始化后检索,这解释了为什么this.props.data在getInitialState中未定义。我建议在componentWillMount中触发loadCommentsFromServer以尽早触发异步操作,并且可以在组件安装之前设置state。
不要在setInitialState中设置messageBox1的状态,而是尝试使用这样的componentWillReceiveProps。当道具改变时,它将保证你的状态更新。
componentWillReceiveProps(newProps) {
this.setState({ nameWithQualifier: 'Mr. ' + newProps.data.pageName })
}
但是,如果在此嵌套的messageBox1组件呈现之前异步数据可用,您可能还希望在messageBox1上执行此操作以确保初始呈现状态是最新的:
componentWillMount() {
this.setState({ nameWithQualifier: 'Mr. ' + this.props.data.pageName })
}
因此,如果你真的想这样做,我建议上面的两条建议
然而,在大多数情况下,似乎没有必要使用它的道具设置组件状态。也许尝试这样的事情:
注释框中的组件的渲染函数将pageName作为prop:
发送 render: function () {
return (
<div className="commentBox">
<MessageBox1 pageName={this.state.data.pageName}/>
</div>
);
}
在messageBox渲染功能中,您可以通过直接访问道具来简化过程。它会给你相同的结果。
render: function() {
return (<div>
<div>{'Mr. ' + this.props.pageName}</div>
<div> {this.props.pageName}</div>
</div>
);
}
这将适用于这个简单的情况,除非您出于某种原因需要更改messageBox1中的道具,因为道具是它们所在的组件不可变的。它们只会在父组件更改传递的内容时更新。