2016-05-09 29 views
2

这里的子组件是一小段代码,我已经尝试了:无法读取getInitialState和ComponentDidMount道具数据对象在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组件中的一个状态变量。这里的问题是,我无法读取道具变量。 “this.props.data”在MessageBox1组件的getInitialState和ComponentDidMount中未定义。而在渲染功能中,我可以看到正确的值。我已经尝试了几个能够读取getInitialState中的道具数据的例子。为什么这不在这里发生?请帮忙。我在控制台中没有任何错误。

回答

2

我相信你对反应组件的生命周期有些困惑。

我建议您快速阅读本文,了解每个生命周期方法何时会被调用。 http://busypeoples.github.io/post/react-component-lifecycle/

在getInitialState方法中的messagebox1中,像这样初始化状态结构,以防止在道具可用之前访问道具。

{ nameWithQualifier: '' } 

您正在调用异步操作来获取数据,因此无法保证何时会检索到数据。然而,根据你现在的样子(在componentDidMount上),它会在messageBox1被初始化之后总是被检索到,这就解释了为什么this.props.data在getInitialState中是未定义的。我建议触发componentWillMount中的loadCommentsFromServer以尽可能早地触发异步操作,并且可以在组件挂载之前设置setState。

而不是设置setInitialState中的messageBox1的状态尝试使用componentWillReceiveProps像这样。它会保证你的状态在道具改变时更新。

componentWillReceiveProps(newProps) { 
    this.setState({ nameWithQualifier: 'Mr. ' + newProps.data.pageName }) 
} 

然而,如果是偶然的异步数据是可用在此之前嵌套messageBox1组件呈现你可能也想做到这一点就messageBox1,以确保国家是最新的初始渲染:

componentWillMount() { 
    this.setState({ nameWithQualifier: 'Mr. ' + this.props.data.pageName }) 
} 

所以如果你真的想这样做,我建议上述

  1. 2项建议在调用你的componentWillMount Ajax请求得到请求发送脱离稍早
  2. 上componentWillReceiveProps更新您的子组件的状态(其中每一次将更新您的状态道具更新)

但是设置您的组件状态与它的道具似乎在大多数情况下没有必要。也许尝试是这样的:

在commentBox组件的渲染功能发送页面名下降为道具:

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内的道具,因为道具都是由他们居住在该组件是不可改变的。他们只会更新,如果父组件的变化是什么传诵。

+1

现在,我对混乱的反应生命周期并不是一个秘密。谢谢。 – User1230321

+0

@ user2155657不客气。我强烈建议我将链接添加到顶部,当我看到像这样的意外行为时,对我来说它总是一个很好的参考。 – jmancherje

+0

当然。谢谢 – User1230321