首页 文章

React:显示加载器,而背景图像正在加载导致setState错误

提问于
浏览
2

我正在尝试创建一个加载背景图像的组件(在同构应用程序中) . 虽然图像正在加载,但我想显示一个微调器但是我一直想出这个错误:

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op.

在init时,加载状态设置为false(因此如果禁用js,则不显示微调器)

constructor (props) {
    super(props);
    this.state = {
        loading: false
    };
}

在componentDidMount上,加载状态设置为 true ,使用 props.src 创建图像,加载或错误调用函数时 .

componentDidMount = () => {
    this.setState({loading: true});

    this.image = new Image();
    this.image.src = this.props.src;
    this.image.onload = this.handleImageLoaded;
    this.image.onerror = this.handleImageError;
}

这些函数会将加载状态设置为 false

handleImageLoaded = () => {
    this.setState({loading: false});
}

handleImageError = () => {
    this.setState({loading: false});
}

如果state为true(这会渲染),渲染函数将显示一个单独的组件 Loader ,我将更改img load上的内联样式背景 .

return (
        <div className={style.wrapper}>
            <div className={style.background} style='background-image:'>
                <Loader loading={this.state.loading} />
            </div>
        </div>
    );

2 回答

  • 2

    这是一个非常常见的问题,错误消息告诉您或多或少发生了什么 - 您试图在unmountedcomponent上调用 setState . 在 componentDidMount 中,您开始加载图像并设置回调( handleImageLoaded )以在图像加载(或错误)时执行 . 在此回调中,您调用 setState . 由于加载是异步的,因此当组件不再在文档中时,它可以很容易地完成 .

    处理此问题的方法曾经是在修改状态之前询问组件是否仍然加载:

    handleImageLoaded = () => {
        if(this.isMounted())
           this.setState({loading: false});
    }
    

    不幸的是,这会给你一个警告,说 isMounted() 已被弃用 . 你现在应该做的基本上是这样的:

    {
        isStillMounted: true,
        componentWillUnmount: () => { this.isStillMounted = false; },
        handleImageLoaded: () => {
            if(this.isStillMounted)
                this.setState({loading: false});
        }
    }
    

    理想情况下,您只需取消 componentWillUnmount 中的加载,但我不能't think that' .

    另外,就像1ven所指出的那样,如果你在 componentWillUnmount 删除那些处理程序是个好主意,以防止任何潜在的内存泄漏 .

  • 0

    在大多数情况下,在未安装的组件中调用 setState 时会显示此错误 .

    在您的情况下,据我所知,由于某种原因,您的组件在加载图像之前就已卸载 .

    要避免此错误,您应该始终删除不在render函数中定义的任何事件侦听器,如下所示:

    this.image.onload = undefined;
    this.image.onerror = undefined;
    

相关问题