无法读取reactjs中子组件中的getInitialState和ComponentDidMount中的props数据对象

时间:2016-05-09 01:29:01

标签: javascript jquery reactjs

以下是我尝试过的一小段代码:

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中读取道具数据。为什么这不会发生?请帮忙。我在控制台中没有任何错误。

1 个答案:

答案 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 })
}

因此,如果你真的想这样做,我建议上面的两条建议

  1. 在componentWillMount中调用您的ajax请求以获取先前发送的请求
  2. 在componentWillReceiveProps上更新你的子组件中的状态(每次道具更新时都会更新你的状态)
  3. 然而,在大多数情况下,似乎没有必要使用它的道具设置组件状态。也许尝试这样的事情:

    注释框中的

    组件的渲染函数将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中的道具,因为道具是它们所在的组件不可变的。它们只会在父组件更改传递的内容时更新。