Вы не должны использовать <Link> вне <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>
)

Есть идеи, что я здесь делаю не так?

Здесь ссылка Песочница, чтобы продемонстрировать проблему.

Ответ 1

Я предполагаю, что вы используете React-Router V4, как вы использовали то же самое в исходной ссылке Sandbox.

Вы предоставляете компонент Main в вызове ReactDOM.render который отображает компонент Link а компонент Main находится за пределами Router, поэтому он выдает ошибку:

Вы не должны использовать <Link> вне <Router>

Изменения:

  1. Используйте любой из этих маршрутизаторов, BrowserRouter/HashRouter и т.д., Потому что вы используете React-Router V4.

  2. Маршрутизатор может иметь только одного дочернего элемента, поэтому оберните все маршруты в div или Switch.

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

И т.п.


Также проверьте этот ответ: Вложенные маршруты с реакции маршрутизатора v4

Ответ 2

Для пользователей JEST

если вы используете Jest для тестирования, и эта ошибка возникает, просто оберните ваш компонент <BrowserRouter>

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

Ответ 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, поэтому вы должны визуализировать его родительский компонент.

Ответ 4

Компонент "Заключить ссылку" внутри компонента BrowserRouter

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

Ответ 5

Всякий раз, когда вы пытаетесь показать 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 Header.js react-router-dom но этот компонент был размещен вне <BrowserRouter>, это приведет к той же ошибке, что и <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.

Ответ 6

Напишите маршрутизатор вместо Основной в рендеринг (последняя строка в коде). Как это ReactDOM.render(маршрутизатор, document.getElementById('root'));

Ответ 7

Сделайте это просто:

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

и не забудь: import { BrowserRouter } from "react-router-dom";

Ответ 8

Я получил эту ошибку, потому что я импортировал повторно используемый компонент из библиотеки npm, а версии react-router-dom не совпадали.

Поэтому убедитесь, что вы используете одну и ту же версию в обоих местах!

Ответ 9

Если вы не хотите сильно меняться, используйте ниже код внутри метода onClick().

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