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

jon*_*rpe 12 reactjs jestjs react-router react-router-dom react-testing-library

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

\n
const renderInRouter = () => {\n  const history = createMemoryHistory();\n  const wrapper = render(\n    <Router history={history}>\n      <MyPage />\n    </Router>\n  );\n  return { ...wrapper, history };\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这在 v5.3 之前工作得很好,但升级到 v6 后我得到:

\n
 FAIL  ./demo.test.js\n  \xe2\x9c\x95 works (205 ms)\n\n  \xe2\x97\x8f works\n\n    TypeError: Cannot read properties of undefined (reading \'pathname\')\n\n      at Router (../packages/react-router/index.tsx:281:5)\n\n      ...\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
interface RouterProps {\n  basename?: string;\n  children?: React.ReactNode;\n  location: Partial<Location> | string;\n  navigationType?: NavigationType;\n  navigator: Navigator;\n  static?: boolean;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

目前尚不清楚 v6 的等效项是什么;我尝试切换到navigator={history}但仍然遇到相同的错误。

\n

要重现,请将以下文件复制到新目录中,npm install然后运行npm test

\n

package.json

\n
 FAIL  ./demo.test.js\n  \xe2\x9c\x95 works (205 ms)\n\n  \xe2\x97\x8f works\n\n    TypeError: Cannot read properties of undefined (reading \'pathname\')\n\n      at Router (../packages/react-router/index.tsx:281:5)\n\n      ...\n
Run Code Online (Sandbox Code Playgroud)\n

index.test.js:

\n
interface RouterProps {\n  basename?: string;\n  children?: React.ReactNode;\n  location: Partial<Location> | string;\n  navigationType?: NavigationType;\n  navigator: Navigator;\n  static?: boolean;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

jon*_*rpe 43

React Router v6 将历史记录分成多个部分,对于此用例,相关部分是导航器位置。此更改在UseuseNavigate而不是 中useHistoryNavigator有所暗示,您可以在 props中使用的类型的定义中看到它Router

export declare type Navigator = Omit<History, "action" | "location" | "back" | "forward" | "listen" | "block">;
Run Code Online (Sandbox Code Playgroud)

只是更改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>
  );
});
Run Code Online (Sandbox Code Playgroud)

请注意,从 React Router 6.4 开始,history不再作为依赖项包含在内,因此如果您没有显式安装它,则需要将其添加回来。


Fra*_*ndi 5

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

如果你有这个: import { Router } from "react-router-dom";

将导入更改为: import { BrowserRouter as Router } from "react-router-dom";