【问题标题】:"Cannot read properties of undefined (reading 'pathname')" when testing pages in the v6 React Router在 v6 React 路由器中测试页面时“无法读取未定义的属性(读取'路径名')”
【发布时间】:2021-12-19 21:05:04
【问题描述】:

在使用<Link>s 测试组件时,例如在我对Recommended approach for route-based tests within routes of 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)

      ...

migration docs 未涵盖此用例,v6 到目前为止还没有测试指南,尽管API reference 确实表明不再需要 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-testing-library react-router-v6


    【解决方案1】:

    React Router v6 将历史分成多个部分,对于这个用例,相关部分是 navigatorlocationUse useNavigate instead of useHistory 中暗示了这一变化,您可以在 Router 道具中使用的 Navigator 类型的定义中看到它:

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

    只是将history={history} 更改为navigator={history} 仍然留下location 属性,路由器试图从中访问pathname (among other properties),未定义。要让测试再次运行,请按如下方式更新渲染:

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

    【讨论】:

    • @ml242 没有minimal reproducible example 很难说出您的问题可能是什么。如果您将此处显示的模式应用到您的testRenderer,我希望它可以工作,但我真的不知道它在做什么。
    • @ml242 请用minimal reproducible example 提出一个正确的问题。链接到这篇文章作为描述你的研究的一部分。
    【解决方案2】:

    这是我对这个问题的解决方案,来自我在 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>
      );
    });
    

    【讨论】:

    • 这是 explicitly flagged unstable_ 作为一个“可能会引入错误的新的、未记录的 API”。在它变得稳定之前,最好不要编写依赖它的代码。
    • 好的,谢谢,我会牢记这一点,我在尝试您的解决方案时这样做了,并且我的 URL 已更改,但这些更改未在应用程序组件上复制,可能是由于应用的 SPA 特性。
    猜你喜欢
    • 1970-01-01
    • 2017-12-30
    • 2017-09-23
    • 2021-12-31
    • 1970-01-01
    • 2021-03-25
    • 2021-11-24
    • 1970-01-01
    • 2015-05-25
    相关资源
    最近更新 更多