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

升级React18与React Testing Library13后,如何结合createRoot使用custom render?

React 18 + React Testing Library 13 自定义渲染报错解决方案

升级后出现的这类报错,核心原因是 React 18 强制要求使用createRoot进行渲染,而旧的自定义render逻辑没适配这个变化,结合 React Testing Library(RTL)13 的新特性,你可以按以下方式修复:

1. 调整自定义渲染函数写法

RTL 13 已经内置适配了 React 18 的createRoot,不需要手动调用 ReactDOM 的createRoot,直接基于 RTL 的render封装即可:

import { render } from '@testing-library/react';
import YourAppProvider from '../path-to-your-provider';

// 带全局Provider的自定义渲染
const customRender = (ui, options = {}) => {
  const Wrapper = ({ children }) => (
    <YourAppProvider>{children}</YourAppProvider>
  );

  return render(ui, { wrapper: Wrapper, ...options });
};

export default customRender;

如果是特殊场景必须手动处理 root,要保证和 RTL 的生命周期对齐,避免重复渲染:

import { screen } from '@testing-library/react';
import { createRoot } from 'react-dom/client';

const customRender = (ui, { container = document.createElement('div') } = {}) => {
  const root = createRoot(container);
  root.render(ui);
  
  return {
    container,
    ...screen,
    unmount: () => root.unmount(), // 适配React18的卸载方式
  };
};

2. 替换旧的卸载逻辑

React 18 移除了ReactDOM.unmountComponentAtNode,测试中如果有手动卸载逻辑,要换成 root 的unmount方法,或者直接使用 RTL 返回的unmount函数:

// 旧写法(React17及以下)
// import ReactDOM from 'react-dom';
// ReactDOM.unmountComponentAtNode(container);

// 新写法
const { unmount } = customRender(<YourComponent />);
unmount();

3. 检查依赖版本兼容性

确保你的依赖版本完全匹配:

  • react & react-dom:18.x
  • @testing-library/react:13.x
  • @testing-library/dom:需和 RTL 13 版本匹配(通常安装 RTL 时会自动对齐)

常见报错排查

  • 若报错createRoot(...): Target container is not a DOM element:检查测试用的 container 是否被提前销毁,建议每个测试用例创建独立的 container。
  • 若报错Rendered more times than expected:排查自定义 render 是否重复调用了渲染方法(比如同时调用了root.render和 RTL 的render),只保留一次渲染即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:26:01