"Cannot read properties of undefined (reading 'pathname')" 在 v6 React Router 中测试页面时
"Cannot read properties of undefined (reading 'pathname')" when testing pages in the v6 React Router
在使用 <Link>
测试组件时,例如在我对 的回答中,我经常使用以下模式来访问当前的 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 has no testing guides so far and, although the 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 中通过了。
React Router v6 将历史分成多个部分,对于这个用例,相关部分是 navigator 和 location。 Use 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>
);
});
这是我对这个问题的解决方案,来自我在 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>
);
});
在使用 <Link>
测试组件时,例如在我对 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 has no testing guides so far and, although the 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 中通过了。
React Router v6 将历史分成多个部分,对于这个用例,相关部分是 navigator 和 location。 Use 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>
);
});
这是我对这个问题的解决方案,来自我在 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>
);
});