您不应该在<router>之外使用<link />

时间:2018-02-06 10:03:39

标签: reactjs react-router jsx

我试图在示例应用程序中设置react-router,并且我收到以下错误:

Main

我的应用设置如下:

父组件

export default () => (
  <div>
    <h1>
      <Link to="/">Redux example</Link>
    </h1>
  </div>
)

子/ this.getView().byId(...)组件

this.byId(...)

知道我在这里做错了吗?

Here's a Sandbox link来证明这个问题。

12 个答案:

答案 0 :(得分:19)

我假设您正在使用React-Router V4,因为您在原始Sandbox Link.

中使用了相同的方法

您在Main的调用中呈现ReactDOM.render组件,其呈现Link而主要组件位于Router之外,这就是为什么它是抛出错误:

  

您不应该使用&lt; Link&gt;在&lt;路由器&gt;

之外

<强>更改

  1. 使用 these Routers ,BrowserRouter / HashRouter等中的任何一个......,因为您使用的是React-Router V4。

  2. 路由器只能有一个子节点,因此请将所有路由包裹在divSwitch中。

  3. React-Router V4,没有嵌套路由的概念,如果你想使用嵌套路由,那么直接在该组件内定义那些路由。

  4. 使用以下每项更改检查 this working example

    父组件:

    const App = () => (
      <BrowserRouter>
        <div className="sans-serif">
          <Route path="/" component={Main} />
          <Route path="/view/:postId" component={Single} />
        </div>
      </BrowserRouter>
    );
    
    render(<App />, document.getElementById('root'));
    
    来自路线的

    Main组件
    import React from 'react';
    import { Link } from 'react-router-dom';
    
    export default () => (
      <div>
        <h1>
          <Link to="/">Redux example</Link>
        </h1>
      </div>
    )
    

    同时查看以下答案:Nested routes with react router v4

答案 1 :(得分:8)

对于JEST用户

如果您使用Jest进行测试,并且发生了此错误,只需用<BrowserRouter>包裹您的组件

describe('Test suits for MyComponentWithLink', () => {
it('should match with snapshot', () => {
const tree = renderer
  .create(
    <BrowserRouter>
      <MyComponentWithLink/>
    </BrowserRouter>
  )
  .toJSON();
 expect(tree).toMatchSnapshot();
 });
});

答案 2 :(得分:3)

我有点想出这个代码:

Main

我认为错误是因为您正在呈现Main组件,而Router组件对array一无所知,因此您必须呈现其父组件。< / p>

答案 3 :(得分:1)

将Link组件包含在BrowserRouter组件内

 export default () => (
  <div>
   <h1>
      <BrowserRouter>
        <Link to="/">Redux example</Link>
      </BrowserRouter>
    </h1>
  </div>
)

答案 4 :(得分:1)

每当您尝试在Link以外的页面上显示BrowserRouter时,都会出现该错误。

此错误消息实质上是说,不是我们<Router>子级的任何组件都不能包含任何与React Router相关的组件。

您需要将组件层次结构迁移到上面第一个答案中看到的样子。对于审查此帖子的其他人可能需要查看更多示例。

假设您有一个Header.js组件,如下所示:

import React from 'react';
import { Link } from 'react-router-dom';

const Header = () => {
    return (
        <div className="ui secondary pointing menu">
            <Link to="/" className="item">
                Streamy
            </Link>
            <div className="right menu">
                <Link to="/" className="item">
                    All Streams
                </Link>
            </div>
        </div>
    );
};

export default Header;

您的App.js文件如下所示:

import React from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom';
import StreamCreate from './streams/StreamCreate';
import StreamEdit from './streams/StreamEdit';
import StreamDelete from './streams/StreamDelete';
import StreamList from './streams/StreamList';
import StreamShow from './streams/StreamShow';
import Header from './Header';

const App = () => {
  return (
    <div className="ui container">
      <Header />
      <BrowserRouter>
        <div>
        <Route path="/" exact component={StreamList} />
        <Route path="/streams/new" exact component={StreamCreate} />
        <Route path="/streams/edit" exact component={StreamEdit} />
        <Route path="/streams/delete" exact component={StreamDelete} />
        <Route path="/streams/show" exact component={StreamShow} />
        </div> 
      </BrowserRouter>
    </div>
  );
};

export default App;

请注意,Header.js组件正在使用Link中的react-router-dom标记,但是组件位于<BrowserRouter>之外,这将导致与OP的一次体验。在这种情况下,您可以一步一步进行更正:

import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import StreamCreate from './streams/StreamCreate';
import StreamEdit from './streams/StreamEdit';
import StreamDelete from './streams/StreamDelete';
import StreamList from './streams/StreamList';
import StreamShow from './streams/StreamShow';
import Header from './Header';

const App = () => {
  return (
    <div className="ui container">
      <BrowserRouter>
        <div>
        <Header />
        <Route path="/" exact component={StreamList} />
        <Route path="/streams/new" exact component={StreamCreate} />
        <Route path="/streams/edit" exact component={StreamEdit} />
        <Route path="/streams/delete" exact component={StreamDelete} />
        <Route path="/streams/show" exact component={StreamShow} />
        </div> 
      </BrowserRouter>
    </div>
  );
};

export default App;

请仔细检查并确保您拥有<Header />或任何组件,不仅包含在<BrowserRouter>内,而且还包含在<div>内,否则您将收到错误消息路由器可能只有一个孩子,而孩子是指<div>的孩子。 <BrowserRouter>之类的所有其他内容和组件都必须位于层次结构中。

因此,现在Route<Header />标记内<BrowserRouter>的子代,它可以成功利用<div>元素。

答案 5 :(得分:1)

简单点:

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

不要忘记:import { BrowserRouter } from "react-router-dom";

答案 6 :(得分:0)

渲染(代码中的最后一行)中写路由器代替。 像这样 ReactDOM.render(router,document.getElementById(&#39; root&#39;));

答案 7 :(得分:0)

我收到此错误是因为我正在从npm库中导入可重用组件,而react-router-dom的版本不匹配。

因此请确保您在两个地方都使用相同的版本!

答案 8 :(得分:0)

您可以将Link组件放置在Router组件内。像这样:

 <Router>
        <Route path='/complete-profiles' component={Profiles} />
        <Link to='/complete-profiles'>
          <div>Completed Profiles</div>
        </Link>
      </Router>

答案 9 :(得分:0)

我的回答基于此 article。这是一个简单的解决方案。

// index.test.tsx
import React from "react";
import { render, screen } from "@testing-library/react";
import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";
import Login from ".";

it("should display Login", () => {
  const history = createBrowserHistory();
  render(
    <Router history={history}>
      <Login />
    </Router>
  );
  const linkElement = screen.getByText(/Login/i);
  expect(linkElement).toBeInTheDocument();
});

答案 10 :(得分:0)

为什么不尝试创建另一个仅使用“react-router-dom”中的 BrowserRouter 的组件,并将您的组件与其中的 Link 一起包装起来。

const ReduxExample () => (
  <div>
    <h1>
      <Link to="/">Redux example</Link>
    </h1>
  </div>
)

然后你可以这样做

const NewReduxExample = () => {
   <BrowserRouter>
     <ReduxExample />
   </BrowserRouter>
};

答案 11 :(得分:-8)

如果您不想改变太多,请在onClick()方法中使用以下代码。

this.props.history.push('/');