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

自定义JS应用嵌入React组件时如何正确卸载清理组件

正确卸载React组件的方案

直接调用DOM元素的remove()方法删除挂载节点无法完成React侧的清理,会导致组件的卸载生命周期不触发、内部注册的事件监听/定时器/异步任务无法被正常回收,引发内存泄漏。

你需要使用React官方提供的卸载API,按「先触发React组件卸载 → 再移除DOM节点 → 清空引用」的顺序操作,不同React版本的API有区别:


React 16 版本(匹配你示例中的写法)

第一步:修改React侧代码,导出专用卸载方法

// ReactModal.jsx
import React from "react";
import ReactDOM from "react-dom";

class ReactModal extends React.Component {
    componentWillUnmount() {
        // 组件内部的清理逻辑统一写在这里:移除全局事件、清除定时器、取消未完成的接口请求等
        console.log("组件已正常卸载,执行内部清理");
    }
    render() {
        return <h2>React Modal</h2>
    }
}

export const renderReactModal = (domElem) => {
    ReactDOM.render(
        <ReactModal />,
        domElem
    );
}

// 新增卸载方法,调用React官方API完成组件卸载
export const unmountReactModal = (domElem) => {
    ReactDOM.unmountComponentAtNode(domElem);
}

第二步:修改业务侧的关闭逻辑

// MyApp.js
import { renderReactModal, unmountReactModal } from "./ReactModal.jsx";

class MyApp {
    openReactModal() {
        this.modalDomElem = document.createElement("div");
        // 注意:原代码document.append写法有误,元素需要挂载到document.body下
        document.body.append(this.modalDomElem);
        renderReactModal(this.modalDomElem);
    }

    closeReactModal() {
        // 1. 先触发React组件卸载,执行所有清理逻辑
        unmountReactModal(this.modalDomElem);
        // 2. 再移除DOM节点
        this.modalDomElem.remove();
        // 3. 清空引用,辅助垃圾回收
        this.modalDomElem = null;
    }
}

React 18 版本(当前主流版本)

React 18 废弃了ReactDOM.render和unmountComponentAtNodeAPI,改用root实例的方式管理挂载卸载:

// ReactModal.jsx
import React from "react";
import { createRoot } from "react-dom/client";

class ReactModal extends React.Component {
    componentWillUnmount() {
        // 组件内部清理逻辑和React16一致
        console.log("组件已正常卸载,执行内部清理");
    }
    render() {
        return <h2>React Modal</h2>
    }
}

// 缓存root实例,卸载时需要使用
let modalRoot = null;

export const renderReactModal = (domElem) => {
    modalRoot = createRoot(domElem);
    modalRoot.render(<ReactModal />);
}

export const unmountReactModal = () => {
    if (modalRoot) {
        // 调用root实例的unmount方法触发卸载
        modalRoot.unmount();
        modalRoot = null;
    }
}

业务侧的关闭逻辑和React16版本一致,先调用unmountReactModal,再移除DOM、清空引用即可。


注意事项

  • 如果使用函数组件,所有清理逻辑需要写在useEffect的返回函数中,组件卸载时该函数会自动执行:
    const ReactModal = () => {
        useEffect(() => {
            const handleEsc = (e) => e.key === 'Escape' && closeModal();
            window.addEventListener('keydown', handleEsc);
            // 卸载时执行的清理逻辑
            return () => window.removeEventListener('keydown', handleEsc);
        }, []);
    
        return <h2>React Modal</h2>
    }
    
  • 不要颠倒卸载顺序:必须等React完成组件卸载后再移除DOM节点,否则React在卸载过程中找不到对应DOM节点会抛出错误。
  • 卸载完成后及时清空DOM、root实例的引用,避免不必要的内存占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:48:27