Javascript 反应:加载背景图像时显示加载程序导致设置状态错误
我正在尝试创建一个组件(在一个同构应用程序中)来加载背景图像。在加载图像时,我想显示一个微调器,但我不断出现以下错误:Javascript 反应:加载背景图像时显示加载程序导致设置状态错误,javascript,reactjs,Javascript,Reactjs,我正在尝试创建一个组件(在一个同构应用程序中)来加载背景图像。在加载图像时,我想显示一个微调器,但我不断出现以下错误: 警告:设置状态(…):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了setState()。这是禁止的。 在init上,加载状态被设置为false(因此如果js被禁用,它不会显示微调器) 在componentDidMount上,加载状态设置为true,并使用props.src创建图像,加载或出错时调用函数 componentDidMount = () =&g
警告:设置状态(…):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了setState()。这是禁止的。
在init上,加载状态被设置为false(因此如果js被禁用,它不会显示微调器)
在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});
}
如果状态为true(这会渲染),渲染函数将显示一个单独的组件加载程序,我将在img加载时更改内联样式背景
return (
<div className={style.wrapper}>
<div className={style.background} style='background-image:'>
<Loader loading={this.state.loading} />
</div>
</div>
);
返回(
);
在大多数情况下,在未安装的组件中调用setState
时会显示此错误
在您的情况下,据我所知,由于某种原因,您的组件在加载映像之前正在卸载
为避免此错误,应始终删除未在渲染函数中定义的任何事件侦听器,如下所示:
this.image.onload = undefined;
this.image.onerror = undefined;
这是一个非常常见的问题,错误消息或多或少地告诉您发生了什么-您试图在未安装的组件上调用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});
}
}
理想情况下,您只需取消组件中的加载即可卸载,但我认为这是不可能的
此外,正如1ven所指出的,如果您使用的是本机事件而不是React事件,那么最好删除componentWillUnmount
中的那些处理程序,以防止任何潜在的内存泄漏。您可以发布加载程序
组件代码吗?
{
isStillMounted: true,
componentWillUnmount: () => { this.isStillMounted = false; },
handleImageLoaded: () => {
if(this.isStillMounted)
this.setState({loading: false});
}
}