升级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
相关产品推荐
相关产品推荐

