您不应在<Router>外使用<Link>


77

我正在尝试在示例应用程序中设置react-router,但出现以下错误:

You should not use <Link> outside a <Router>

我的应用程序设置如下:

父组件

const router = (
  <div className="sans-serif">
    <Router histpry={browserHistory}>
      <Route path="/" component={Main}>
        <IndexRoute component={PhotoGrid}></IndexRoute>
        <Route path="/view/:postId" component={Single}></Route>
      </Route>
    </Router>
  </div>
);

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

子/Main组件

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

知道我在做什么错吗?

这是一个沙盒链接来演示该问题。


请提及您使用的是哪个版本react-router,因为您对索引路由使用了不同的方法。
Haider Ali Anjum '18

更新某些应用程序依赖项后,由于热重新加载失败,我收到了此消息。手动退出并重新启动开发服务器即可解决此问题。仅供参考,以防其他人突然弹出消息。
本·弗莱彻

Answers:


52

我假设您正在使用React-Router V4,就像您在原始Sandbox Link中使用的一样

您呈现Main在调用组件ReactDOM.render用来渲染Link和主要成分是外面Router,这就是为什么它被抛出的错误:

您不应在<Router>外使用<Link>

变化

  1. 使用这些路由器,BrowserRouter / HashRouter等中的任何一个,因为您使用的是React-Router V4。

  2. 路由器只能有一个孩子,因此将所有路由包装在div交换机中

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


请检查每个更改的工作示例

父组件:

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

等等。


还要检查以下答案:使用React Router V4的嵌套路由


67

对于JEST用户

如果您使用Jest进行测试,并且发生此错误,则只需用 <BrowserRouter>

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

4
你救了我。谢谢
StrugglingCoder

2
正是我想要的。谢谢
digitalh2o

@MBehtemam,您拯救了我的一天!
lmiguelvargasf

@MBehtemam,非常感谢。它为我工作。
Mo1

此答案使用react-test-renderer,它不是create-react-app内置的。如果您使用内置的@testing-library/react,请render(<BrowserRouter><MyComponent/></BrowserRouter>);改用。
Timmy Chan

11

将Link组件包含在BrowserRouter组件内

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

6

每当您尝试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>标签,它可以成功地利用的Link元素。


3

我有点想出这段代码:

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

// import componentns
import Main from './components/Main';
import PhotoGrid from './components/PhotoGrid';
import Single from './components/Single';

// import react router
import { Router, Route, IndexRoute, BrowserRouter, browserHistory} from 'react-router-dom'

class MainComponent extends React.Component {
  render() {
    return (
      <div>
        <BrowserRouter history={browserHistory}>
          <Route path="/" component={Main} >
            <IndexRoute component={PhotoGrid}></IndexRoute>
            <Route path="/view/:postId" component={Single}></Route>
          </Route>
        </BrowserRouter>
      </div>
    );
  }
}

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

我认为错误是因为您正在渲染Main组件,而Main组件对此一无所知Router,因此您必须渲染其父组件。



1

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

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


0

渲染中将Router代替Main写入(代码的最后一行)。像这样ReactDOM.render(router,document.getElementById('root'));


0

您可以将链接组件放在路由器组件中。像这样:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.