你不应该在 <Router> 之外使用 <Link>

IT技术 reactjs react-router jsx
2021-03-30 02:11:24

我正在尝试在示例应用程序中设置 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>
)

知道我在这里做错了什么吗?

这是一个 Sandbox 链接来演示这个问题。

6个回答

对于JEST用户

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

describe('Test suits for MyComponentWithLink', () => {
it('should match with snapshot', () => {
const tree = renderer
  .create(
    <BrowserRouter>
      <MyComponentWithLink/>
    </BrowserRouter>
  )
  .toJSON();
 expect(tree).toMatchSnapshot();
 });
});
这个答案使用react-test-renderer,它不是为 create-react-app 内置的。如果您使用内置的@testing-library/react,请render(<BrowserRouter><MyComponent/></BrowserRouter>);改用 。
2021-05-27 02:11:24
包裹它<MemoryRouter>而不是<BrowserRouter>因为<MemoryRouter>它的重量更轻。
2021-06-07 02:11:24

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

您正在Main调用ReactDOM.render渲染 aLink并且 Main 组件在 之外的组件Router,这就是它抛出错误的原因:

你不应该在 <Router> 之外使用 <Link>

变化

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

  2. 路由器只能有一个子节点,因此将所有路由都包装在 adivSwitch 中

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

等等。


还要检查这个答案:Nested routes with react router v4

将 Link 组件包含在 BrowserRouter 组件中

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

每当您尝试Link在 之外的页面上显示 a时,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标签 fromreact-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元素。

让它变得简单:

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

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