React18测试报错createRoot目标容器非DOM元素的解决方法
解决React测试中“createRoot(...): Target container is not a DOM element”错误
问题场景
使用React 18.2.0版本,运行index.test.jsx测试CountryDetail组件时,触发错误:createRoot(...): Target container is not a DOM element。
相关代码如下:
测试文件 index.test.jsx
import {render, screen} from "@testing-library/react"; import CountryDetail from "./index"; test('Country detail renders correctly',()=>{ render(<CountryDetail />) const element = screen.getByText('Corona Virus Data') expect(element).toBeInTheDocument() } )
App.js
import { BrowserRouter, Routes, Route } from "react-router-dom"; import HomePage from "routes/home"; import CountryDetail from "routes/countryDetail"; function App() { return ( <div className="app"> <BrowserRouter> <Routes> <Route path="/" element={ <HomePage />} /> <Route path="/:country" element={<CountryDetail />} /> </Routes> </BrowserRouter> </div> ); } export default App;
index.js
const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <Provider store={store}> <PersistGate loading={null} persistor={persistStore(store)}> <App /> </PersistGate> </Provider> </React.StrictMode> );
错误原因
- 缺少路由上下文:
CountryDetail是路由组件,依赖react-router-dom的上下文(比如路由参数/:country),单独渲染时没有路由环境支撑,可能引发内部逻辑错误。 - 组件内部直接操作DOM:如果
CountryDetail内部调用了ReactDOM.createRoot挂载到某个DOM节点,测试环境中该节点不存在,就会触发此错误。
解决方法
方法1:给组件添加路由上下文包裹
因为CountryDetail是路由组件,测试时需要用MemoryRouter模拟路由环境,同时传入必要的路由参数:
修改后的测试代码:
import { render, screen } from "@testing-library/react"; import CountryDetail from "./index"; import { MemoryRouter, Routes, Route } from "react-router-dom"; test('Country detail renders correctly', () => { // 用MemoryRouter模拟路由,initialEntries设置当前路由路径 render( <MemoryRouter initialEntries={['/test-country']}> <Routes> <Route path="/:country" element={<CountryDetail />} /> </Routes> </MemoryRouter> ); const element = screen.getByText('Corona Virus Data'); expect(element).toBeInTheDocument(); });
方法2:模拟组件依赖的DOM容器(如果组件内部直接操作DOM)
如果CountryDetail内部有自行调用ReactDOM.createRoot挂载到特定DOM节点的逻辑,需要在测试前提前创建该节点:
修改后的测试代码:
import { render, screen } from "@testing-library/react"; import CountryDetail from "./index"; import { MemoryRouter, Routes, Route } from "react-router-dom"; test('Country detail renders correctly', () => { // 提前创建组件需要的DOM容器 const targetContainer = document.createElement('div'); targetContainer.id = '组件中使用的DOM节点ID'; // 替换成实际ID document.body.appendChild(targetContainer); // 包裹路由环境 render( <MemoryRouter initialEntries={['/test-country']}> <Routes> <Route path="/:country" element={<CountryDetail />} /> </Routes> </MemoryRouter> ); const element = screen.getByText('Corona Virus Data'); expect(element).toBeInTheDocument(); // 测试后清理DOM document.body.removeChild(targetContainer); });
说明
MemoryRouter是react-router-dom提供的测试工具,用于在无浏览器环境下模拟路由上下文。- 若组件依赖Redux或其他全局状态,还需要在测试中包裹对应的
Provider,确保组件能获取到状态上下文。
内容的提问来源于stack exchange,提问作者Sena Akbulut
相关产品推荐
相关产品推荐

