Skip to content

outline: [2, 3]

React 18 ReactDOM.createRoot 替代 render()

问题描述

升级到 React 18 后,许多开发者会遇到以下警告信息:

WARNING

Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

这个警告出现在使用 create-react-app 创建新项目时:

bash
npx create-react-app my-app

问题原因

React 18 在 2022 年 3 月 29 日发布,引入了新的根API(root API)。之前的 ReactDOM.render() 方法已被弃用,虽然目前仍能在兼容模式下运行,但未来可能会被完全移除。

解决方案

方法一:基本迁移方案

将原来的 ReactDOM.render() 替换为新的 createRoot API:

js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();
js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

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

reportWebVitals();

方法二:简化导入方式

可以直接从 react-dom/client 导入 createRoot

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

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

方法三:TypeScript 版本

对于 TypeScript 项目,需要添加类型断言:

ts
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

reportWebVitals();

方法四:使用 React Router 的项目

如果你的应用使用了 React Router,更新方式如下:

js
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

const container = document.getElementById("root");
const root = createRoot(container);
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

代码对比

js
import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(<App />, document.getElementById('root'));
js
import { createRoot } from 'react-dom/client';

createRoot(document.getElementById('root')).render(<App />);

注意事项

WARNING

虽然 React 18 目前仍然支持 ReactDOM.render() 的兼容模式,但建议尽快迁移到新的 API,因为:

  1. 旧 API 已被标记为 deprecated
  2. 新 API 启用了 React 18 的所有新特性
  3. 未来版本可能会完全移除对旧 API 的支持

为什么需要这个更改?

React 18 引入的新根API提供了更好的性能和改进的并发特性(Concurrent Features)。新的 createRoot API 为以下功能奠定了基础:

  • 自动批处理(Automatic Batching)
  • 过渡更新(Transitions)
  • Suspense 服务端渲染

扩展阅读

现在你已经了解了如何在 React 18 中正确初始化应用,赶快更新你的项目代码吧!