【问题标题】:React: Display loader whilst background image is loading results in setState error反应:在加载背景图像时显示加载器导致 setState 错误
【发布时间】:2016-12-15 02:39:07
【问题描述】:

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

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.

在初始化时,加载状态设置为 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 加载时更改内联样式背景。

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

【问题讨论】:

  • 可以发Loader组件代码吗?

标签: javascript reactjs


【解决方案1】:

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

据我了解,在您的情况下,由于某种原因,您的组件在您加载图像之前正在卸载。

为避免此错误,您应始终删除未在渲染函数中定义的任何事件侦听器,如下所示:

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

【讨论】:

    【解决方案2】:

    这是一个很常见的问题,错误消息或多或少地告诉你发生了什么——你试图在一个未安装的组件上调用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 中的加载,但我认为这是不可能的。

    另外,就像 1ven 指出的那样,如果您使用的是原生事件而不是 React 事件,最好删除 componentWillUnmount 中的这些处理程序,以防止任何潜在的内存泄漏。

    【讨论】:

      猜你喜欢
      • 2019-08-25
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多