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

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>
);

错误原因

  1. 缺少路由上下文:CountryDetail是路由组件,依赖react-router-dom的上下文(比如路由参数/:country),单独渲染时没有路由环境支撑,可能引发内部逻辑错误。
  2. 组件内部直接操作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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 09:00:30