【问题标题】:Invariant failed: You should not use <Route> outside a <Router>不变式失败:您不应该在 <Router> 之外使用 <Route>
【发布时间】:2019-08-28 08:19:18
【问题描述】:

我在React 应用程序中使用react-router-dom 进行路由。我的应用程序的一部分提取到另一个包中。依赖项列表如下所示:

./app/dashboard/package.json

{
  "dependencies": {
    "@app/components": "^1.0.0",
    "react": "^16.8.5",
    "react-dom": "^16.8.5",
    "react-router-dom": "^5.0.0"
  }
}

./app/components/package.json

{
  "peerDependencies": {
    "react-router-dom": "^5.0.0"
  }
}

当我使用来自@app/components 的组件需要来自react-router-dom 的组件时,我收到此错误:

Uncaught Error: Invariant failed: You should not use <Route> outside a <Router> 
The above error occurred in the <Context.Consumer> component:
Uncaught (in promise) Error: Invariant failed: You should not use <Route> outside a <Router>

为什么会抛出这个错误?在App.js 我使用BrowserRouter

import React, { Suspense } from 'react';
import { Switch, Route } from 'react-router-dom';
import { Placeholder } from '@app/components';

const Auth = React.lazy(() => import(/* webpackPrefetch: true */ './pages/Auth'));
const Index = React.lazy(() => import(/* webpackPrefetch: true */ './pages/Index'));

const App = () => (
  <Suspense fallback={<Placeholder />}>
    <Switch>
      <Route path="/auth" component={Auth} />
      <Route path="/" component={Index} />
    </Switch>
  </Suspense>
);

export default App;

client.jsx

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

import App from './App';

render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root'),
);

【问题讨论】:

  • 如果有人添加 &lt;Router&gt; 标签以尝试解决此问题,请注意,您必须导入 BrowserRouter as Router 才能使其正常工作。

标签: reactjs react-router react-router-dom


【解决方案1】:

我通过改变解决了这个问题:

import {Route, Switch} from "react-router";

import {Route, Switch} from "react-router-dom";

只需添加 -dom。

【讨论】:

  • 我在从“react-router”导入重定向时遇到了同样的问题
【解决方案2】:

我在测试时遇到了这个问题,并通过用路由器包装我的测试组件来解决它。

import React from 'react';
import ReactDom from 'react-dom';
import Header from '../components/Header/Header';
import { BrowserRouter } from 'react-router-dom';

it('renders Header without crashing', () => {
  const div = document.createElement('div');

  ReactDom.render(
    <BrowserRouter>
      <Header />
    </BrowserRouter>, 
  div);

  ReactDom.unmountComponentAtNode(div);
});

Jest, Enzyme: Invariant Violation: You should not use or , To 测试一个组件(使用 Jest),其中包含您的路由器并使用您的路由器 需要在您的测试中导入路由器,而不是在您的组件导入{ BrowserRouter as Invariant Violation:您不应该使用或 withRouter() 外部根据反应路由器 4 文档, 组件被认为是有效的,我可以在其中创建组件 由 s 组成,然后将它们导入另一个组件并 放在一个 .

【讨论】:

  • 谢谢。这正是我测试所需要的。
  • 你不应该使用&lt;MemoryRouter&gt; 进行测试吗?
【解决方案3】:

两个 React 实例的问题

【讨论】:

  • 尝试渲染 的多个实例导致我的代码出现此异常,感谢您的提示!
  • @rodurico 我面临同样的问题。你是怎么解决的?
  • @SawanPatodia 我不得不重绘根组件。您必须在整个项目的单个 中包含一个
【解决方案4】:

您应该在Router标签中包含Route标签,Link标签。

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const Home = () => {
  return (
    <div>
      <p>Home</p>
    </div>
  );
};

const About = () => {
  return (
    <div>
      <p>About</p>
    </div>
  );
};

const Contact = () => {
  return (
    <div>
      <p>Contact</p>
    </div>
  );
};
class App extends Component {
  render() {
    return (
        <Router>
              <div>
              <h1>W3Adda - Simple SPA</h1>
                <nav>
                  <ul>
                    <li>
                      <Link to="/">Home</Link>
                    </li>
                    <li>
                      <Link to="/about">About</Link>
                    </li>
                    <li>
                      <Link to="/contact">Users</Link>
                    </li>
                  </ul>
                </nav>

                <Route path="/" exact component={Home} />
                <Route path="/about" component={About} />
                <Route path="/contact" component={Contact} />
              </div>
        </Router>
    );
  }
}

export default App;

【讨论】:

    【解决方案5】:

    我解决了这个问题,只是将react-router-dom 中的BrowserRouter 导入index.js 并添加:

    <BrowserRouter>
       <App>
     </BrowserRouter>
    

    在:

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

    【讨论】:

      【解决方案6】:

      我在测试链接到项目的组件时得到了这个(使用npm link),因为react-router-dom 加载了不止一次,以下解决方案适用于我的情况:

      webpack.config.js里面我加了:

      resolve: {
          alias: {        
              'react-router-dom': path.resolve('./node_modules/react-router-dom')
          }
      }
      

      【讨论】:

      • 如果有人来这里是因为 而不是 的相同问题,我需要添加 react-routerreact-router-dom 作为这样的别名才能正常工作,即使我没有 react-router 作为依赖项。
      • '祝福你!!在处理具有 react-router-dom 作为依赖项的本地包时也会发生这种情况
      【解决方案7】:

      您需要从react-router-dom 导入命名导出Router 并将其包裹在您的开关/路由组件周围。

      const App = () => (
        <Router>
          <Suspense fallback={<Placeholder />}>
            <Switch>
              <Route path="/auth" component={Auth} />
              <Route path="/" component={Index} />
            </Switch>
          </Suspense>
        </Router>
      );
      

      【讨论】:

      • 我把我所有的应用都封装在client.jsx
      • 这个解决方案也对我有用,但我有点惊讶。就像 OP 一样,我的客户端代码中有 Router
      【解决方案8】:

      我在使用重定向组件时遇到了类似的问题。原来我是从“react-router”而不是“react-router-dom”调用重定向。

      Error: Invariant failed: You should not use <Redirect> outside a <Router>
      

      【讨论】:

        【解决方案9】:

        我的 Create React App 在运行测试时遇到了同样的问题,我通过将 &lt;Router&gt;&lt;/Router 放在 App.js 中而不是像往常一样放在 Index.js 中解决了这个问题。

        之前:

        索引.js

        ReactDOM.render(
            <React.StrictMode>
                <GlobalStyle />
                <Router>
                    <App />
                </Router>
            </React.StrictMode>,
        document.getElementById('root')
        );
        

        App.js

        return (
            <div className="App">
                <Header />
                <Route path="/blabla" component={Whatever}
            </div>
        )
        

        之后:

        Index.js:

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

        App.js:

        return (
            <div className="App">
                <Router>
                    <Header />
                    <Route path="/blabla" component={Whatever}
                </Router>
            </div>
        )
        

        【讨论】:

          【解决方案10】:

          我在使用 CRA 和组件库创建的主应用程序中遇到了类似的情况。我们有两个独立工作的react-router-dom 实例。库中的组件使用&lt;Link&gt;,而父应用使用&lt;Router&gt;

          受@Pavel 回答的启发,我发现这个问题可以通过添加别名来解决。如果您使用的是 webpack,您可以更改解析 react-router-dom 模块的方式。您可以覆盖 webpack 查找依赖项的默认顺序,并使您的父应用程序 node_modules 比组件节点模块解析顺序更优先:

          别名.js

          const fs = require('fs');
          const path = require('path');
          
          const directory = fs.realpathSync(process.cwd());
          const resolveApp = (relativePath) => path.resolve(directory, relativePath);
          
          module.exports = {
            react: resolveApp('node_modules/react'),
            'react-router-dom': resolveApp('node_modules/react-router-dom'),
          };
          

          config-override.js 用来覆盖默认 CRA 设置:

          const { addWebpackAlias, override, removeModuleScopePlugin } = require('customize-cra');
          const aliases = require('./aliases');
          
          module.exports = override(removeModuleScopePlugin(), addWebpackAlias(aliases));
          

          或者对于 webpack.config.js(如果不是 CRA):

          resolve: {
            alias: {
              "react-router-dom": path.resolve(appFolder, "node_modules", "react-router-dom"),
           }
          }
          

          【讨论】:

            【解决方案11】:

            我通过从 MyComponent 中删除“react-router-dom”的依赖项解决了这个神秘的错误。我删除了 'node_modules/react-router-dom' 和 'package.json' 我的应用程序结构如下:

                AppFolder
                ├── README.md
                ├── build
                ├── node_modules
                │   ├── react-router-dom
                ├── package-lock.json
                ├── package.json
                ├── public
                │   ├── favicon.ico
                │   ├── index.html
                │   └── manifest.json
                └── src
                    ├── App.css
                    ├── App.js
                    ├── App.test.js
                    ├── index.js
                    ├── redux
                    │   ├── reducers.js
                    │   └── store.js
                    └── serviceWorker.js
            
            
                MyComponent
                ├── README.md
                ├── dist
                ├── node_modules
                │   ├── react-router-dom
                ├── package-lock.json
                ├── package.json
                ├── rollup.config.js
                └── src
                    ├── index.js
                    ├── styles.css
                    └── test.js
            

            这是 App.js 的源代码

            import MyComponent from 'MyComponent'
            
            export default App(){
             return (
             <div className="App">
                <HashRouter>
                  <div>
                    <header className="App-header">
            
                    </header>
                    <Route path="/home" component={MyComponent}/>
                  </div>
                </HashRouter>
              </div>)
            }
            

            这是 MyComponent 的导出

            export default withRouter(MyComponent);
            

            如果 'react-router-dom' 留在组件文件夹中,则会出现错误。

            【讨论】:

            • 我的问题是我同时安装了react-router-domreact-router。我删除了后者,我的问题就解决了。
            【解决方案12】:

            我通过将父组件包装在路由器中来解决此错误。

            解决错误之前

            <Header />
            <div className="col-md-12 pd-0-0">
              <div className="row">
                <Sidebar />
                <div className="col-sm-10 col-md-10 pd-0-0" style={style}>
                  <Router>
                    <Switch>
                      <Route path="/dashboard/check-in" component={CheckIn} />
                      <Route path="/dashboard/deals" component={Deals} />
                      <Route path="/dashboard/events" component={Events} />
                      <Route path="/dashboard/invoice" component={Invoice} />
                      <Route path="/dashboard/notification" component={Notification} />
                      <Route path="/dashboard/profile" component={Profile} />
                      <Route path="/dashboard/redemption" component={Redemptions} />
                      <Route path="/dashboard/restriction-management" component={RestrictionManagement} />
                    </Switch>
                  </Router>
                </div>
              </div>
            </div>
            

            解决错误后

            <Router>
              <Header />
              <div className="col-md-12 pd-0-0">
                <div className="row">
                  <Sidebar />
                  <div className="col-sm-10 col-md-10 pd-0-0" style={style}>
                    <Switch>
                      <Route path="/dashboard/check-in" component={CheckIn} />
                      <Route path="/dashboard/deals" component={Deals} />
                      <Route path="/dashboard/events" component={Events} />
                      <Route path="/dashboard/invoice" component={Invoice} />
                      <Route path="/dashboard/notification" component={Notification} />
                      <Route path="/dashboard/profile" component={Profile} />
                      <Route path="/dashboard/redemption" component={Redemptions} />
                      <Route path="/dashboard/restriction-management" component={RestrictionManagement} />
                    </Switch>
                  </div>
                </div>
              </div>
            </Router>
            

            【讨论】:

              【解决方案13】:

              实际上问题出在您正在执行路由的根组件中,您不应在组件中添加Router 标记之外的任何组件,该组件仅期望由RouteRouter 下包装的单个/多个组件在那个组件中。

              错误的代码(但它会运行,但你正在创建错误) -

              function App() {
                return (
                  <div className="App">
                    <Header/>
                    <Router>
                      <Switch>
                        <Route path="/" exact>
                          <Home />
                        </Route>
                      </Switch>
                    </Router>
                  </div>
                );
              }
              

              我只删除了 &lt;Header/&gt; ,它解决了问题。

              写代码 -

              function App() {
                return (
                  <div className="App">
                    <Router>
                      <Switch>
                        <Route path="/" exact>
                          <Home />
                        </Route>
                      </Switch>
                    </Router>
                  </div>
                );
              }
              

              【讨论】:

                【解决方案14】:

                只需在“react-router-dom”上更改“react-router”

                import {Route} from "react-router";
                

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

                【讨论】:

                • 效果很好!
                【解决方案15】:

                在我的情况下,这个错误是由于混淆了 react-router 和 react-router-dom 中的东西(withRouter、MemoryRouter)的使用引起的。通过仅使用 react-router-dom 中的内容,不变错误消失了。希望这对任何人都有帮助。

                【讨论】:

                  【解决方案16】:

                  在没有导入的组件中使用&lt;Link&gt; 标记可能会出现此错误,请尝试从'react-router-dom' 导入BrowserRouter

                  import {BrowserRouter , Link} from 'react-router-dom';
                  

                  然后确保将链接的标签包装在标签中

                  【讨论】:

                    【解决方案17】:

                    在组件之外使用 Router。将所有组件封装在 Router 中,然后就可以在组件中使用 Link

                    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

                    <Router>
                            <Appbar />
                            <Switch>
                              <Route exact path="/" component={Home} />
                              <Route path="/mac" exact component={Mac} />
                            </Switch>
                           <Footer />
                          </Router>
                    

                    【讨论】:

                    • 我不确定这样包裹路由器是否是一个好习惯
                    【解决方案18】:

                    我设法通过从router.js 中删除&lt;BrowserRouter&gt; 并将其包含在app.js 中来解决问题

                    export default function  Routes() {
                      return (
                         
                          <Switch>
                            <Route path="/" exact component={Home} />
                            <Route path="/book" component={Book} />
                            <Route path="/client" component={Client} />
                            <Route path="/rent" component={Rent} />
                            <Route path="/dash" component={Dash} />
                          </Switch>
                        
                      );
                    }
                    function App() {
                      return (
                        <div>
                      
                      <BrowserRouter>
                        <Header></Header>
                        
                        <Routes/>
                        </BrowserRouter>
                        </div>
                      );
                    }
                    

                    【讨论】:

                      【解决方案19】:

                      我已经通过导入解决了这个问题

                      import {BrowserRouter as Router, Route} from 'react-router-dom';
                      

                      并将所有Route组件包装在Router组件下

                       <Router>
                           <Route exact path='/' component={HomePage} />
                       </Router>
                      

                      【讨论】:

                        【解决方案20】:

                        我在尝试替换 Solidus 应用中的 Rails 视图时遇到了类似的问题。

                        我的解决方案是编辑 vie 以使用我刚刚添加但显然尚未完全配置的 React 路由器。

                        比如我编辑了views/spree/home/index.html来自:

                        <%= javascript_pack_tag 'application' %>
                        <%= react_component("Home/Index") %>
                        

                        到:

                        <%= javascript_pack_tag 'application' %>
                        <%= react_component("Routes") %>
                        

                        更多参考,这里是我的javascript/components/Route.js

                        import React from "react";
                        import { BrowserRouter as Router, Route } from "react-router-dom";
                        import Home from "./Home/Index";
                        import Product from "./Products/Show";
                        
                        class Routes extends React.Component {
                          render() {
                            return (
                              <Router>
                                <Route exact path="/" component={Home} />
                                <Route path="/products/:slug" component={Product} />
                              </Router>
                            );
                          };
                        };
                        
                        export default Routes;
                        

                        【讨论】:

                          【解决方案21】:

                          如果您使用 GatsbyJS 并遇到此错误,只需更改您的

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

                          import { Link } from 'gatsby';
                          

                          【讨论】:

                            【解决方案22】:

                            最简单的答案就在 reactstrap for Navbar 的官方文档中,请参阅此网站https://reactstrap.github.io/components/navbar/

                            他们指导我们需要使用这个导入

                            import {NavLink} from 'reactstrap';
                            

                            【讨论】:

                              【解决方案23】:

                              document.getElementById('root') 之后的渲染调用结束时有一个悬挂逗号。

                              render(
                                <BrowserRouter>
                                  <App />
                                </BrowserRouter>,
                                document.getElementById('root'),
                              );
                              

                              【讨论】:

                              • 没问题。 JS 允许这样做。
                              猜你喜欢
                              • 2020-08-04
                              • 2020-12-10
                              • 2020-09-03
                              • 2020-04-18
                              • 2020-10-23
                              • 2020-02-04
                              • 2021-01-16
                              • 2020-08-12
                              • 1970-01-01
                              相关资源
                              最近更新 更多