【问题标题】:React best way to handle empty object before mount?在安装之前反应处理空对象的最佳方法?
【发布时间】:2015-04-21 21:11:19
【问题描述】:

我有一个 React 类,它想渲染一个如下所示的对象:

data: {
    title: "haha",
    description: {
        country: "US",
        year: "1996"
    }
}

但是,当 React 想要渲染它时,它给出了一个错误。

未捕获的错误:不变违规:receiveComponent(...):只能更新已安装的组件

我认为问题出在 getInitialState 中,我将我的数据声明为一个空对象,所以当我在超时后获得完整的数据对象时,React 会尝试将我的数据对象映射到组件,但它给出了错误。

但有趣的是,我访问 this.props.title.title 没有问题,但访问 this.props.title.description.country 没有问题,它会给未定义

但是,当我 console.log 时,我可以看到我的对象。但是 React 无法访问它!

我的猜测是当 React 从空对象初始化时,它只会用数据对象的第一和第二级初始化虚拟 DOM。

那是因为,当我尝试访问 this.props.data.data.title 是可以的,但不是 this.props.data.data.description.country

下面是我的代码

var BookBox = React.createClass({
    getInitialState: function() {
        return { data: {} };
    },
    componentWillMount: function() {
        var that = this;
        setTimeout(function() {
            console.log('timeout');
            that.setState({
                data: {
                    title: "haha",
                    description: {
                        country: "US",
                        year: "1996"
                    }
                }
            });
        }, 2000);
    },
    render: function() {
        return (
            <div>
                <h1>{this.state.data.title}</h1>
                <TestBox title={this.state.data} />
            </div>
        );
    }
});

var TestBox = React.createClass({
    render: function() {
        console.log(this.props.title);
        return (
            <div>
                <p>{ this.props.title.description.country }</p>
                <p>{ this.props.title.title }</p>
            </div>
        );
    }
})

我可以知道处理这个问题的最佳方法是什么吗?我应该在 getInitialState 中初始化我的数据对象结构还是有更好的方法?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    我认为您收到Can only update a mounted component 错误是因为您同时使用componentWillMount 和settimeout,但您不知道在settimeout 函数触发时组件是否已安装。

    既然你事先知道你的状态是什么,我认为最好从getInitialState函数返回你的数据。

    您也可以使用componentDidMount 代替componentWillMount 函数。这样您就可以确保在调用 componentDidMount 时组件已安装。

    任何时候你使用像settimeout这样的asycn函数或xhr调用,你应该在回调函数中使用this.isMounted(),以检查在回调触发时组件是否仍然挂载。

    例如,如果您事先不知道状态,您可以在componentDidMount 函数中触发xhr 调用,检查成功回调中的this.isMounted() 和setState。

    至于&lt;p&gt;{ this.props.title.description.country }&lt;/p&gt; 行上的错误:在初始渲染时this.state.data(BookBox)是一个空对象,this.props.title(TestBox)也是一个空对象。访问空对象的 ({ }) title 属性是 undefined。那里没问题。访问description 也是undefined。但是访问undefined 的country 是错误的。为避免此错误,您可以创建一个description 变量:description = this.props.title.description || {} 并使用&lt;p&gt;{description.country}&lt;/p&gt; 确保您的代码在this.props.title 为空时不会中断。

    【讨论】:

    • 如果您复制我的工作示例,并删除

      { this.props.title.title }

      ,则渲染它没有问题,但如果您添加

      { this.props.title.description.country }

      ,那东西坏了,我也不知道为什么……
    • 在初始渲染时 this.state.data (BookBox) 是一个空对象,this.props.title(TestBox) 也是如此。访问空对象的 ({ }) title 属性是 undefined。那里没问题。访问description 也是undefined。但访问undefined 的country 是错误的。
    • 既然你事先知道初始状态,你应该使用getInitialState函数。如果您不知道状态,您可以在 componentDidMount 函数中触发 xhr 调用,检查成功回调中的 this.isMounted() 和 setState。
    • 另外在TestBox 组件中,我会使用description = this.props.title.description || {} 和&lt;p&gt;{description.country}&lt;/p&gt; 来确保this.props.title 为空时我的代码不会中断。
    • @EviSong 如果在 XHR 结果到达时组件已卸载,我看不到太多选择,只能什么都不做。该组件已从 DOM 中删除。启动新的 xhr 不会重新安装组件。组件不能自行挂载。我认为您应该检查组件被其父级卸载的原因。也许将 XHR 调用移动到父组件,该组件卸载组件并在结果到达时重新安装/更新它。
    猜你喜欢
    • 2013-03-08
    • 1970-01-01
    • 2018-10-01
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 2010-12-02
    相关资源
    最近更新 更多