非React项目中ReactDOM渲染组件移除后无法二次渲染的问题
问题解决方案
问题原因
当模态框隐藏时直接通过innerHTML = ''清空#modal_body,会绕过React的组件卸载流程,导致React内部保留着对已销毁DOM节点的引用,再次调用ReactDOM.render()时无法正确重新挂载组件。
解决方法
1. 适配React 17及以下版本的方案
修改模态框隐藏逻辑,先通过React官方API卸载组件,再执行DOM清理:
function hideModal() { const modalBody = document.getElementById('modal_body'); // 先卸载React组件,确保生命周期正常执行 ReactDOM.unmountComponentAtNode(modalBody); // 再执行原有隐藏逻辑 modalBody.innerHTML = ''; modalBody.style.display = 'none'; }
同时在打开模态框的点击事件中,提前清理残留组件,保证重新渲染的环境干净:
$(document).on("click", ".js-popup-form", function () { showModal(); const modalBody = document.getElementById("modal_body"); // 清理可能残留的组件实例 ReactDOM.unmountComponentAtNode(modalBody); // 重新渲染获客表单 ReactDOM.render(<LeadForm />, modalBody); });
2. React 18+推荐方案(使用createRoot API)
React 18弃用了ReactDOM.render,改用createRoot管理根节点,能更稳定处理组件挂载/卸载:
// 打开模态框的点击事件 $(document).on("click", ".js-popup-form", function () { showModal(); const modalBody = document.getElementById("modal_body"); // 卸载旧的根实例(如果存在) if (modalBody._reactRoot) { modalBody._reactRoot.unmount(); } // 创建新根节点并渲染表单 const root = ReactDOM.createRoot(modalBody); root.render(<LeadForm />); // 保存根实例引用,方便后续卸载 modalBody._reactRoot = root; }); // 隐藏模态框的函数 function hideModal() { const modalBody = document.getElementById('modal_body'); // 卸载React根实例 if (modalBody._reactRoot) { modalBody._reactRoot.unmount(); delete modalBody._reactRoot; } // 执行原有隐藏逻辑 modalBody.innerHTML = ''; modalBody.style.display = 'none'; }
核心思路
必须通过React提供的API管理组件的挂载与卸载,避免直接操作DOM修改React渲染的内容,确保React内部状态与实际DOM保持一致,就能解决重复打开模态框时组件无法重新渲染的问题。
内容的提问来源于stack exchange,提问作者Robbert
相关产品推荐
相关产品推荐

