生态与帮助 · React 19
适配
React 19 适配指南
Semi Design 现已支持 React 19。由于 React 19 引入了一些底层 API 的变更,使用时需要进行简单的适配。

React 19 的特殊之处

React 19 移除了两个 Semi 组件库依赖的 API:

1. ReactDOM.render 被移除

React 19 移除了传统的 ReactDOM.render API,改为使用 createRoot。Semi 的以下组件依赖此 API 来动态挂载内容:
  • Modal.info() / Modal.success() / Modal.error() / Modal.warning() / Modal.confirm()
  • Toast.info() / Toast.success() / Toast.error() / Toast.warning()
  • Notification.info() / Notification.success() / Notification.error() / Notification.warning()

2. ReactDOM.findDOMNode 被移除

React 19 移除了 ReactDOM.findDOMNode API,该 API 用于从类组件实例获取对应的 DOM 节点。Semi 的以下组件受影响:
  • Tooltip 及所有基于它的弹出层组件(PopoverPopConfirmDropdown 等)

为什么需要 adapter?

由于 Semi 需要同时支持 React 16/17/18/19,而 React 19 的 createRoot 位于 react-dom/client 子路径中,直接在库内部导入会导致低版本 React 报错。因此我们采用 adapter 模式,让 React 19 用户显式注入所需的 API。

快速开始

安装

无论你使用的是 React 16、17、18 还是 19,都使用同一个包:

React 19 用户(重要)

如果你的项目使用 React 19,需要在应用入口文件的最顶部导入 adapter:
然后正常使用 Semi 组件:

React 16/17/18 用户

对于 React 16、17、18 项目,无需任何额外配置,直接使用即可:

注意事项

Tooltip 与类组件的限制

由于 React 19 移除了 ReactDOM.findDOMNode,当 Tooltip(及基于它的 PopoverPopConfirmDropdown 等)的 children 是类组件时,可能无法正确获取 DOM 节点进行定位。
受影响的场景
解决方案:用 DOM 元素包裹类组件
不受影响的场景
  • 函数组件配合 forwardRef 正确转发 ref 的情况
  • 原生 DOM 元素(如 <span><div><button> 等)

错误提示

如果你在 React 19 中忘记导入 adapter,控制台会显示以下错误:
看到此错误时,请在入口文件顶部添加:

常见问题

Q: 在 React 18 中导入 adapter 会有问题吗?
A: 不会。在 React 18 中,Semi 会自动检测并使用内置的 createRoot,adapter 的导入不会产生副作用。
Q: adapter 做了什么?
A: adapter 只做一件事:将 React 19 的 createRoot 函数注入到 Semi 内部,使 Modal、Toast、Notification 等组件能够正常工作。代码非常简单:
Q: 为什么 adapter 必须在最顶部导入?
A: 因为 adapter 需要在任何 Semi 组件渲染之前完成 createRoot 的注入。如果在组件已经开始渲染后才导入,可能会导致首次渲染失败。
Q: 我之前使用的是 @douyinfe/semi-ui-19,如何迁移?
A:
  1. 卸载 @douyinfe/semi-ui-19
  2. 安装 @douyinfe/semi-ui(如果还没安装)
  3. 将所有 from '@douyinfe/semi-ui-19' 改为 from '@douyinfe/semi-ui'
  4. 在入口文件顶部添加 import '@douyinfe/semi-ui/react19-adapter'

技术细节

版本兼容性矩阵

React 版本是否需要 adapterReactDOM.rendercreateRoot
16.x✅ 使用❌ 不存在
17.x✅ 使用❌ 不存在
18.x⚠️ 已废弃✅ 自动使用
19.x❌ 已移除✅ 需注入

adapter 的工作原理

  1. React 16/17:使用传统的 ReactDOM.renderReactDOM.unmountComponentAtNode
  2. React 18:自动检测并使用 react-dom 导出的 createRoot
  3. React 19:createRoot 不再从 react-dom 直接导出,需要从 react-dom/client 导入,通过 adapter 注入