组件卸载后反应更新状态(内存泄漏)



我正在构建一个react应用程序(我是javascript的专家),并在组件卸载后尝试更新状态。

react应用程序的背景:作为学校项目的一部分,我必须为一个小型剧院综合体建立一个电影票预订服务,在网络应用程序的主页上,我有一个图像"旋转木马",每5秒更新一次图像。

以下是正在运行的主页:https://apollo-9dd16.web.app/

(图像加载时间只是因为我选择了相当大的图像,将被修复)-第一次访问页面时的加载屏幕也是因为从firebase加载所有内容需要很长时间(所有内容都通过firebase数据库动态更新)如果有办法让它更快,请让我知道

此外,我已经浏览了尽可能多的SO帖子,每个人都建议在执行状态更改之前添加一个检查组件是否已安装,我认为我已经做到了?

无论如何,对于这个问题,出于某种原因,它会说我有内存泄漏,因为我试图在组件卸载后更改组件状态(我无法轻松复制它,但它已经发生了很多次)

import React, {Component} from 'react'
import { Link } from 'react-router-dom'
import MoviesContext from '../contexts/Movies'

/* Todo: 
- Work on the transition between movies
- Work on sending the user to the right place on book now button press
*/
class Home extends Component {
static contextType = MoviesContext
state = {
intervalID:0,
index:1,
prevIndex:0,
nextIndex:2,
picList:[]
}
componentDidMount() {
let mounted = true
const posterURLS = [] // eslint-disable-next-line
this.context.map((movies) => {
posterURLS.push(movies.posterURL)
})
this.setState({picList: posterURLS})
if(mounted) {
const newIntervalId = setInterval(() => {
if (this.state.nextIndex + 1 === this.state.picList.length ){
this.setState({ 
prevIndex: this.state.index,
index: this.state.nextIndex,
nextIndex: 0
})
} else {
this.setState({
prevIndex: this.state.index,
index: this.state.nextIndex,
nextIndex: this.state.nextIndex + 1
})
}
}, 5000);


this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
return () => mounted = false
}
render() {
return (
<div className="font-sans font-light text-theme-white text-4xl z-10 flex justify-center items-center h-screen">
<div className="h-3/4">
<div className="h-full justify-center items-center">
<div className="h-full hidden md:flex">
<img src={this.state.picList[this.state.prevIndex]} alt="this is a movie" className="h-full rounded-2xl -mx-20"/>
<img src={this.state.picList[this.state.nextIndex]} alt="this is a movie" className="h-full rounded-2xl -mx-20"/>
</div>
<div className="absolute inset-10 flex justify-center items-center h-screen">
<img src={this.state.picList[this.state.index]} alt="this is a movie" className="h-3/4 rounded-2xl"/>
</div>
</div>
<div className="absolute inset-0 top-10 flex justify-center items-center">
<Link to="/book" className="bg-theme-light text-theme-black rounded-2xl py-3 px-5 hover:bg-theme-black hover:text-theme-light">Book Now</Link>
</div>
</div>

</div>  
)  
}
}
export default Home

你很接近!发生这种情况的原因是因为这个代码:

/* 1 */  if (mounted) {
/* 2 */    const newIntervalId = setInterval(() => {
/* 3 */      if (this.state.nextIndex + 1 === this.state.picList.length) {
/* 4 */        this.setState({
/* 5 */          prevIndex: this.state.index,
/* 6 */          index: this.state.nextIndex,
/* 7 */          nextIndex: 0,
/* 8 */        });
/* 9 */      } else {
/* 10 */        this.setState({
/* 11 */          prevIndex: this.state.index,
/* 12 */          index: this.state.nextIndex,
/* 13 */          nextIndex: this.state.nextIndex + 1,
/* 14 */        });
/* 15 */      }
/* 16 */    }, 5000);
/* 17 */  
/* 18 */    this.setState((prevState) => {
/* 19 */      return {
/* 20 */        ...prevState,
/* 21 */        intervalId: newIntervalId,
/* 22 */      };
/* 23 */    });
/* 24 */  }
/* 25 */  

第1行(在上面的代码段中)的if (mounted)条件有点太高。您应该将if语句包装在第4行和第10行的setState调用周围,因为这两个调用都在setInterval函数回调中。

目前,代码显示:

  • 如果安装了组件
  • 注册此间隔,每5秒更新一次状态

但我相信你希望你的代码说的是:

  • 如果安装了组件
  • 每5秒更新一次状态,但前提是组件仍处于安装状态
if (mounted) {
const newIntervalId = setInterval(() => {
if (this.state.nextIndex + 1 === this.state.picList.length) {
if (mounted) {
this.setState({
prevIndex: this.state.index,
index: this.state.nextIndex,
nextIndex: 0,
});
}
} else {
if (mounted) {
this.setState({
prevIndex: this.state.index,
index: this.state.nextIndex,
nextIndex: this.state.nextIndex + 1,
});
}
}
}, 5000);
this.setState((prevState) => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}

这应该会在组件已经卸载后修复组件更新。您甚至可以删除上面代码段开头的if (mounted)检查。

发生这种情况的原因是,在执行componentDidMount函数时,mounted变量是true,因此它将注册setInterval回调,并保持每5秒执行一次。

当执行setInterval回调时,mounted变量可能不再是true,但没有什么可以阻止它执行。

最新更新