我正在尝试创建一个加载背景图像的组件(在同构应用程序中)。在加载图像的同时,我想显示一个微调器但是我一直想出这个错误:
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>
);
答案 0 :(得分: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
中删除这些处理程序,以防止任何潜在的内存泄漏。
答案 1 :(得分:0)
在大多数情况下,在未安装的组件中调用setState
时会显示此错误。
在您的情况下,据我所知,出于某种原因,在您加载图片之前,您的组件已卸载。
要避免此错误,应始终删除未在render函数中定义的任何事件侦听器,如下所示:
this.image.onload = undefined;
this.image.onerror = undefined;