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

React 18中如何替换嵌套的ReactDOM.render(原React17实现)

React 18 内层嵌套渲染的迁移解决方案

在 React 18 中,createRoot 替代了原有的 ReactDOM.render,且要求每个 DOM 容器只能对应一个 React 根实例。直接替换内层 ReactDOM.render 为 createRoot 会报错,核心原因是重复创建根实例或容器元素的状态冲突,以下是针对性的解决方案:

1. 外层入口文件升级

首先按照 React 18 要求,将外层的渲染逻辑替换为 createRoot:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

2. 内层嵌套渲染的修正

内层渲染需要避免重复创建根实例,通过 useRef 缓存已创建的根对象,确保同一容器只初始化一次根:

import { createElement, useRef } from "react";
import { createRoot } from "react-dom/client";

// 修正原代码中HTML标签闭合错误
const html = `<div id="my-id">Hi</div>`;

export default function App() {
  // 缓存内层根实例
  const innerRootRef = useRef(null);

  const fillMe = () => {
    const myDiv = document.getElementById("my-id");
    if (!myDiv) return;

    if (innerRootRef.current) {
      // 根实例已存在,直接调用render更新内容
      innerRootRef.current.render(
        createElement("h1", { className: "greeting" }, "Hello")
      );
    } else {
      // 首次创建根实例并缓存
      const innerRoot = createRoot(myDiv);
      innerRoot.render(
        createElement("h1", { className: "greeting" }, "Hello")
      );
      innerRootRef.current = innerRoot;
    }
  };

  return (
    <div className="App">
      <button onClick={fillMe}>fill me</button>
      <div dangerouslySetInnerHTML={{ __html: html }} />
    </div>
  );
}

关键注意事项

  • 禁止重复调用 createRoot:同一 DOM 容器只能初始化一次根实例,重复创建会触发 React 报错。
  • 容器存在性校验:添加 myDiv 存在判断,避免因 DOM 结构异常导致的渲染失败。
  • 修正原代码错误:原 HTML 字符串中的 <div/> 标签闭合错误会导致 DOM 结构异常,需改为 </div>。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:04:54