Не слід використовувати <Link> поза <Router>


80

Я намагаюся налаштувати маршрутизатор реакцій у прикладі програми, і я отримую таку помилку:

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, оскільки ви використовуєте різні підходи для маршрутизації індексів.
Хайдер Алі Анжум

Я отримав це повідомлення через помилку гарячого перезавантаження після оновлення деяких залежностей програми. Вирішення проблеми вирішено вручну із системи виходу та перезапуску сервера розробки. Тільки FYI на випадок, якщо комусь ще не з’явиться повідомлення з нізвідки.
ballenf

Відповіді:


54

Я припускаю, що ви використовуєте React-Router V4, як і в оригінальному посиланні Sandbox.

Ви рендеріть Mainкомпонент у виклику, ReactDOM.renderякий відображає a, Linkа основний компонент знаходиться поза Router, ось чому він видає помилку:

Не слід використовувати <Link> поза <Router>

Зміни :

  1. Використовуйте будь-який із цих маршрутизаторів , BrowserRouter / HashRouter тощо ..., оскільки ви використовуєте React-Router V4.

  2. У маршрутизатора може бути лише одна дитина, тому оберніть усі маршрути в a 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


73

Для користувачів 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, thx за чудове додавання. У мене це спрацювало.
пн.

Ця відповідь використовує react-test-renderer, що не вбудовано в create-response-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>
)

7

Щоразу, коли ви намагаєтесь показати 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

Напишіть маршрутизатор замість Main у візуалізації (останній рядок у коді). Подібно до цього ReactDOM.render (маршрутизатор, document.getElementById ('root'));


0

Ви можете розмістити компонент Link у компонеті маршрутизатора. Щось на зразок цього:

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

-12

Якщо ви не хочете багато чого змінювати, скористайтеся наведеним нижче кодом всередині методу onClick ().

this.props.history.push('/');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.