You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件卸载后更新state引发内存泄漏问题排查求助

React轮播组件内存泄漏问题修复及性能优化方案

内存泄漏核心问题&修复步骤

你代码的问题根源是把函数组件useEffect的生命周期逻辑错误用到了类组件上,还有几个细节疏漏:

  1. 类组件的componentDidMount返回函数不会被自动执行,你写的() => mounted = false清理逻辑完全没有触发,定时器也从来没有被清理,组件卸载后定时器依然在运行调用setState
  2. 你只在创建定时器前判断了mounted状态,定时器内部执行setState时没有加判断,就算mounted逻辑生效也拦不住卸载后的状态更新
  3. 变量名大小写不统一:state中定义的是intervalID(大写D),存储定时器ID时写的是intervalId(小写d),后续根本找不到正确的定时器ID做清理
  4. 遍历context时用了map但没有返回值,属于不规范写法,改成forEach更合适

修复后的完整代码如下:

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
    // 把mounted标记改成实例属性,方便生命周期访问
    _isMounted = false
    state = {
        intervalId:0, // 统一变量名,全小写d
        index:1,
        prevIndex:0,
        nextIndex:2,
        picList:[]
    }
    componentDidMount() {
        this._isMounted = true
        const posterURLS = []
        // 把没用的map改成forEach
        this.context.forEach((movies) => {
            posterURLS.push(movies.posterURL)
        })
        this.setState({picList: posterURLS})

        const newIntervalId = setInterval(() => {
            // 每次更新state前先判断组件是否挂载
            if(!this._isMounted) return
            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({
            intervalId: newIntervalId
        });
    }

    // 新增卸载生命周期,清理定时器+更新挂载标记
    componentWillUnmount() {
        this._isMounted = false
        clearInterval(this.state.intervalId)
    }

    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" loading="lazy"/>
                            <img src={this.state.picList[this.state.nextIndex] || ''} alt="this is a movie" className="h-full rounded-2xl -mx-20" loading="lazy"/>
                        </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

性能优化建议

图片加载优化

  • 把所有海报图转成WebP格式,同视觉质量下体积比JPG/PNG小50%以上,能大幅降低加载耗时
  • 按页面实际展示尺寸裁剪图片,不要直接上传未压缩的原图,比如轮播图最大展示高度为屏幕高度的3/4,按1080p的展示规格裁剪即可
  • 上述代码已经给非当前展示的图片加了loading="lazy"懒加载属性,能避免首次加载时一次性请求所有海报图

首屏加载优化

  • 给Firebase存储的静态资源配置CDN缓存规则,设置合理的缓存时间,避免用户每次访问都重新拉取相同资源
  • 电影列表这类不频繁更新的数据做本地缓存,首次拉取后存在localStorage里,后续用户访问先读本地缓存渲染页面,再后台请求最新数据更新,不用等接口返回才渲染
  • 给首屏需要展示的前3张海报加预加载配置,在页面head中添加<link rel="preload" as="image" href="首屏海报地址">,能提前触发图片加载,提升首屏渲染速度

内容的提问来源于stack exchange,提问作者Toby Clark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 15:15:01