javascript - 不变失败 : You should not use <Switch> outside a <Router>

标签 javascript reactjs react-router jestjs react-testing-library

我添加了 react 路由器以进行基本导航并且工作正常,但是当我运行测试时它返回错误。

Error: Uncaught [Error: Invariant failed: You should not use Switch outside a Router]

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import { BrowserRouter } from "react-router-dom";

import * as serviceWorker from "./serviceWorker";

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById("root")
);

serviceWorker.unregister();

app.js

import React from "react";
import { Normalize } from "styled-normalize";
import { Switch, Route } from "react-router-dom";

import Home from "./pages/Home";
import FooterBarNavigator from "./navigators/FooterBarNavigator";
import Favorites from "./pages/Favorites";
import Finder from "./pages/Finder";
import Notifications from "./pages/Notifications";
import Profile from "./pages/Profile";

function App() {
  return (
    <div className="App">
      <Normalize />
      <FooterBarNavigator />
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/favorites" component={Favorites} />
        <Route exact path="/finder" component={Finder} />
        <Route exact path="/notifications" component={Notifications} />
        <Route exact path="/profile" component={Profile} />
      </Switch>
    </div>
  );
}

export default App;

FooterBarNavigator.js

import React from "react";
import styled from "styled-components";

import homeIcon from "../../assets/icons/home.svg";
import favoritesIcon from "../../assets/icons/favorite.svg";
import serachIcon from "../../assets/icons/search.svg";
import notificationsIcon from "../../assets/icons/notifications.svg";
import profileIcon from "../../assets/icons/profile.svg";
import { Link } from "react-router-dom";

const FooterBarNavigator = () => {
  return (
    <StyledFooterBarNavigator>
      <Link to="/">
        <StyledSectionIcon src={homeIcon} alt="" />
      </Link>
      <Link to="/favorites">
        <StyledSectionIcon src={favoritesIcon} alt="" />
      </Link>
      <Link to="/finder">
        <StyledSectionIcon src={serachIcon} alt="" />
      </Link>
      <Link to="/notifications">
        <StyledSectionIcon src={notificationsIcon} alt="" />
      </Link>
      <Link to="/profile">
        <StyledSectionIcon src={profileIcon} alt="" />
      </Link>
    </StyledFooterBarNavigator>
  );
};

const StyledFooterBarNavigator = styled.div`
  display: grid;
  position: fixed;
  width: 100%;
  bottom: 0;
  grid-gap: 1rem;
  grid-template-columns: repeat(5, auto);
  grid-template-rows: auto;
  align-items: center;
`;

const StyledSectionIcon = styled.img`
  height: 35px;
  padding: 10px;
  margin: auto auto 5px auto;
  display: block;
`;

export default FooterBarNavigator;

app.test.js

import React from 'react';
import { render } from '@testing-library/react';
import App from '../../components/App';

test('renders learn react link', () => {
  const { getByText } = render(<App />);
  const linkElement = getByText(/home/i);
  expect(linkElement).toBeInTheDocument();
});

package.json

{
  "name": "app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-lazyload": "^2.6.8",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.1",
    "styled-components": "^5.1.1",
    "styled-normalize": "^8.0.7"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

最佳答案

在你的index.js中,你通过包含<App />正确地包装你的路由。组件具有 <BrowserRouter /> ,但你在测试中没有这样做,所以只需更改:

const { getByText } = render(<App />);

至:

const { getByText } = render(
    <BrowserRouter>
        <App />
    </BrowserRouter>
);

完整的新测试文件:

import React from 'react';
import { render } from '@testing-library/react';
import { BrowserRouter } from "react-router-dom";
import App from '../../components/App';

test('renders learn react link', () => {
  const { getByText } = render(
    <BrowserRouter>
        <App />
    </BrowserRouter>
);
  const linkElement = getByText(/home/i);
  expect(linkElement).toBeInTheDocument();
});

关于javascript - 不变失败 : You should not use <Switch> outside a <Router>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62710458/

相关文章:

javascript - 如何使用来自 React Router 的路由参数发出 axios 请求,然后根据响应更新状态?

javascript - 无法使用 react 和 href 元素在本地主机中下载 pdf 文件

做普通事情的 javascript 习语

reactjs - 在reactjs中,wrappedComponent.propTypes是什么?

javascript - Ratchet Websockets - 检测断开连接的客户端

javascript - 寻求建议: Reason for maximum update depth exceed

javascript - react 状态改变状态使代码从可见变为隐藏

reactjs - 通过路径从 react-router 获取组件

javascript - 在对象标记中嵌入的 html 页面中调用 javascript 函数

javascript - 如何以响应方式创建水平元素?