【问题标题】:Unable to read props data object in getInitialState and ComponentDidMount in the child component in reactjsreactjs子组件中getInitialState和ComponentDidMount无法读取props数据对象
【发布时间】:2016-09-03 13:13:14
【问题描述】:

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

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

【问题讨论】:

    标签: javascript jquery reactjs


    【解决方案1】:

    我相信您对 React 组件的生命周期有些困惑。

    我建议快速通读这篇文章以了解每个生命周期方法何时被调用。 http://busypeoples.github.io/post/react-component-lifecycle/

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

    { nameWithQualifier: '' }
    

    您正在调用异步操作来获取数据,因此无法保证何时检索数据。但是,根据您现在的方式(在 componentDidMount 上),它将始终在 messageBox1 初始化后检索,这解释了为什么 this.props.data 在 getInitialState 中未定义。建议尽早在componentWillMount中触发你的loadCommentsFromServer来触发异步动作,并且可以在组件挂载之前设置状态。

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

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

    但是,如果在这个嵌套的 messageBox1 组件渲染之前异步数据是可用的,您可能还希望在 messageBox1 上执行此操作以确保状态在初始渲染时是最新的:

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

    所以如果你真的想这样做,我推荐上面的2个建议

    1. 在 componentWillMount 中调用您的 ajax 请求以提前发送请求
    2. 在 componentWillReceiveProps 上更新您的子组件中的状态(每次道具更新时都会更新您的状态)

    但是,在大多数情况下,似乎没有必要使用它的 props 设置组件状态。也许尝试这样的事情:

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

    【讨论】:

    • 现在,我对 React 生命周期感到困惑已经不是什么秘密了。谢谢。
    • @user2155657 不客气。我强烈推荐我在顶部附加的链接,当我看到这样的意外行为时,它对我来说总是一个很好的参考。
    猜你喜欢
    • 2015-09-03
    • 1970-01-01
    • 2019-07-30
    • 2019-01-23
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多