ReactJS如何在不同占位符DOM节点中分别渲染不同组件
React多节点渲染报错解决方案
错误原因
报错和React是否允许多次调用渲染方法无关,React完全支持将不同组件渲染到不同的独立DOM容器中。
报错核心是HTML结构不符合规范:<header>和<footer>标签被放在了<body>标签外部,浏览器构建DOM树时不会将<body>外的这两个节点纳入正常文档DOM树,因此document.getElementById("header")和document.getElementById("footer")获取结果为null,触发目标容器不是DOM元素的报错。
修复方案
方案1:调整HTML结构+多容器渲染(最简单适配)
- 首先修正HTML结构,将
<header>、<footer>都移入<body>标签内部:
<body> <header id="header"></header> <div id="root"></div> <footer id="footer"></footer> <script src="../src/index.js" type="text/jsx"></script> </body>
- 原有渲染代码可直接正常运行(React 17及以下版本):
ReactDOM.render(<Header />, document.getElementById("header")); ReactDOM.render(<Footer />, document.getElementById("footer")); // 主体内容渲染到root不受影响 ReactDOM.render(<App />, document.getElementById("root"));
如果你使用React 18及以上版本,原
ReactDOM.renderAPI已废弃,需使用新的创建根节点API:import { createRoot } from 'react-dom/client'; createRoot(document.getElementById('header')).render(<Header />); createRoot(document.getElementById('footer')).render(<Footer />); createRoot(document.getElementById('root')).render(<App />);
方案2:使用React Portal实现(适合状态共享场景)
如果Header、Footer组件需要和root容器内的组件共享React上下文、全局状态,可采用React Portal方案,所有组件属于同一个React根树,仅渲染输出到指定DOM节点:
- 同样先完成上述HTML结构调整
- 在根组件内使用Portal实现跨节点渲染:
import { createPortal } from 'react-dom'; // React 18导入方式保持一致 function App() { return ( <> {/* 组件逻辑属于App根树,渲染输出到header节点 */} {createPortal(<Header />, document.getElementById('header'))} {/* 页面主体内容正常渲染在root节点内 */} <main> {/* 页面核心内容 */} </main> {/* 组件逻辑属于App根树,渲染输出到footer节点 */} {createPortal(<Footer />, document.getElementById('footer'))} </> ) } // 仅需一次根渲染即可 // React 17及以下写法 ReactDOM.render(<App />, document.getElementById('root')); // React 18及以上写法 // createRoot(document.getElementById('root')).render(<App />);
该方案优势是所有组件共享同一套React上下文、状态管理数据,不会出现多根节点带来的状态隔离问题。
内容的提问来源于stack exchange,提问作者oubaydos
相关产品推荐
相关产品推荐

