在 v6 React Router 中测试页面时“无法读取未定义的属性(读取‘路径名’)”

问题描述 投票:0回答:4

使用

<Link>
测试组件时,例如在我对 react-router 路径中基于路由的测试的推荐方法的回答中,我经常使用以下模式来访问当前
location
以进行测试:

const renderInRouter = () => {
  const history = createMemoryHistory();
  const wrapper = render(
    <Router history={history}>
      <MyPage />
    </Router>
  );
  return { ...wrapper, history };
}

这在 v5.3 之前都运行良好,但升级到 v6 后我得到:

 FAIL  ./demo.test.js
  ✕ works (205 ms)

  ● works

    TypeError: Cannot read properties of undefined (reading 'pathname')

      at Router (../packages/react-router/index.tsx:281:5)

      ...

此用例未在 迁移文档中涵盖,v6 到目前为止还没有测试指南,尽管 API 参考 确实表明不再需要

history
属性:

interface RouterProps {
  basename?: string;
  children?: React.ReactNode;
  location: Partial<Location> | string;
  navigationType?: NavigationType;
  navigator: Navigator;
  static?: boolean;
}

尚不清楚 v6 的等效项是什么;我尝试切换到

navigator={history}
但仍然遇到相同的错误。

要重现,请将以下文件复制到新目录中并运行

npm install
,然后运行
npm test
:

package.json

{
  "name": "router6-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "testEnvironment": "jsdom"
  },
  "babel": {
    "presets": [
      "@babel/preset-react"
    ]
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/preset-react": "^7.16.0",
    "@testing-library/react": "^12.1.2",
    "jest": "^27.3.1",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router-dom": "^6.0.0"
  }
}

index.test.js

const { render } = require("@testing-library/react");
const { createMemoryHistory } = require("history");
const React = require("react");
const { Router } = require("react-router-dom");

it("used to work", () => {
  render(
    <Router history={createMemoryHistory()}></Router>
  );
});

如果您

npm install --save-dev react-router@5
并再次运行
npm test
,您可以看到这在 v5 中通过了。

reactjs jestjs react-router react-router-dom react-testing-library
4个回答
44
投票

React Router v6 将历史记录分成多个部分,对于此用例,相关部分是 navigatorlocation。此更改在 使用

useNavigate
而不是
useHistory
中有所暗示,您可以在
Navigator
属性中使用的
Router
类型的定义中看到它:

export declare type Navigator = Omit<History, "action" | "location" | "back" | "forward" | "listen" | "block">;

仅将

history={history}
更改为
navigator={history}
仍然留下
location
属性,路由器试图从中访问
pathname
以及其他属性),未定义。要使测试再次正常工作,请按如下方式更新渲染:

const { render } = require("@testing-library/react");
const { createMemoryHistory } = require("history");
const React = require("react");
const { Router } = require("react-router-dom");

it("works", () => {
  const history = createMemoryHistory();
  render(
    <Router location={history.location} navigator={history}></Router>
  );
});

注意,从 React Router 6.4 开始,

history
不再作为依赖项包含在内,因此,如果您没有明确安装它,则需要将其添加回来。


5
投票

以防万一有人被困在这个问题上并且在尝试了此处发布的所有解决方案后无法弄清楚发生了什么,请确保您导入的是正确的

Router

如果你有这个:

import { Router } from "react-router-dom"; 

更改导入:

import { BrowserRouter as Router } from "react-router-dom"; 


1
投票

这是我对这个问题的解决方案,来自我一直在 Udemy 上学习的课程:

const { render } = require("@testing-library/react");
const { createBrowserHistory } = require("history");
const React = require("react");
const { unstable_HistoryRouter: HistoryRouter } = require("react-router-dom");

it("works", () => {
  const history = createBrowserHistory();
  render(
    <HistoryRouter history={history}></HistoryRouter>
  );
});

0
投票

如果您使用的react-router-dom版本大于6并且您的导入看起来像这样 从 'react-router-dom' 导入 { BrowserRouter as Router, Route, Routes }; 然后尝试改成这个 从 'react-router-dom' 导入 { Route, BrowserRouter as Router, Routes };

© www.soinside.com 2019 - 2024. All rights reserved.