自定义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
相关产品推荐
相关产品推荐

