Sie sollten <Link> nicht außerhalb eines <Routers> verwenden

77

Ich versuche, den React-Router in einer Beispielanwendung einzurichten, und erhalte die folgende Fehlermeldung:

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

Meine App ist wie folgt eingerichtet:

Übergeordnete Komponente

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

Kind / MainKomponente

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

Irgendeine Idee, was ich hier falsch mache?

Hier ist ein Sandbox-Link , um das Problem zu demonstrieren.

A7DC
quelle
Bitte geben Sie an, von welcher Version Sie verwenden react-router, da Sie unterschiedliche Ansätze für das Index-Routing verwenden.
Haider Ali Anjum
Ich habe diese Meldung aufgrund eines Fehlers beim erneuten Laden nach dem Aktualisieren einiger App-Abhängigkeiten erhalten. Ein manuelles Beenden und Neustarten des Entwicklungsservers löste das Problem. Nur zu Ihrer Information, falls jemand anderes die Nachricht aus dem Nichts auftauchen lässt.
Ben Fletcher

Antworten:

52

Ich gehe davon aus, dass Sie React-Router V4 verwenden, wie Sie es auch im ursprünglichen Sandbox Link verwendet haben.

Sie rendern die MainKomponente in dem Aufruf ReactDOM.render, der a rendert, Linkund die Hauptkomponente befindet sich außerhalb von Router. Deshalb wird der Fehler ausgegeben:

Sie sollten <Link> nicht außerhalb eines <Routers> verwenden

Änderungen :

  1. Verwenden Sie einen dieser Router , BrowserRouter / HashRouter usw., da Sie React-Router V4 verwenden.

  2. Der Router kann nur ein untergeordnetes Element haben. Schließen Sie daher alle Routen in einen divoder Switch ein .

  3. React-Router V4 hat nicht das Konzept verschachtelter Routen. Wenn Sie verschachtelte Routen verwenden möchten, definieren Sie diese Routen direkt in dieser Komponente.


Überprüfen Sie dieses Arbeitsbeispiel mit jeder dieser Änderungen.

Übergeordnete Komponente:

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 Komponente von der Route

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

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

Etc.


Überprüfen Sie auch diese Antwort: Verschachtelte Routen mit React Router v4

Mayank Shukla
quelle
67

Für JEST- Benutzer

Wenn Sie Jest zum Testen verwenden und dieser Fehler auftritt, wickeln Sie Ihre Komponente einfach mit ein <BrowserRouter>

describe('Test suits for MyComponentWithLink', () => {
it('should match with snapshot', () => {
const tree = renderer
  .create(
    <BrowserRouter>
      <MyComponentWithLink/>
    </BrowserRouter>
  )
  .toJSON();
 expect(tree).toMatchSnapshot();
 });
});
MBehtemam
quelle
4
Du hast mich gerettet. Danke
StrugglingCoder
2
Genau das, wonach ich gesucht habe. Vielen Dank
digitalh2o
@ MBehtemam, du hast meinen Tag gerettet!
lmiguelvargasf
@ MBehtemam, danke für die hervorragende Ergänzung. Es hat bei mir funktioniert.
Mo1
Diese Antwort verwendet react-test-renderer, die nicht für die Create-React-App integriert ist. Wenn Sie das eingebaute verwenden @testing-library/react, verwenden Sie render(<BrowserRouter><MyComponent/></BrowserRouter>);stattdessen.
Timmy Chan
11

Schließen Sie die Link-Komponente in die BrowserRouter-Komponente ein

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

Wenn Sie versuchen, Linkeine Seite außerhalb der Seite anzuzeigen BrowserRouter, wird dieser Fehler angezeigt .

Diese Fehlermeldung besagt im Wesentlichen, dass Komponenten, die nicht <Router>untergeordnet sind, keine React Router-bezogenen Komponenten enthalten dürfen.

Sie müssen Ihre Komponentenhierarchie so migrieren, wie Sie es in der ersten Antwort oben sehen. Für alle anderen, die diesen Beitrag lesen und sich möglicherweise weitere Beispiele ansehen müssen.

Angenommen, Sie haben eine Header.jsKomponente, die folgendermaßen aussieht:

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;

Und Ihre App.jsDatei sieht so aus:

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;

Beachten Sie, dass die Header.jsKomponente das LinkTag von verwendet react-router-dom, die Komponente jedoch außerhalb von platziert <BrowserRouter>wurde. Dies führt zu demselben Fehler wie die einzige Erfahrung des OP. In diesem Fall können Sie die Korrektur in einem Zug vornehmen:

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;

Bitte überprüfen Sie sorgfältig und stellen Sie sicher, dass Sie die <Header />oder was auch immer Ihre Komponente nicht nur <BrowserRouter>innerhalb <div>, sondern auch innerhalb der hat. Andernfalls erhalten Sie auch die Fehlermeldung, dass ein Router möglicherweise nur ein Kind hat, das sich auf das Kind bezieht, von dem <div>das Kind ist <BrowserRouter>. Alles andere wie Routeund Komponenten müssen in der Hierarchie enthalten sein.

Das ist nun <Header />ein untergeordnetes Element <BrowserRouter>innerhalb der <div>Tags und kann das LinkElement erfolgreich verwenden .

Daniel
quelle
3

Ich habe mir diesen Code ausgedacht:

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

Ich denke, der Fehler war, weil Sie die MainKomponente gerendert haben und die MainKomponente nichts darüber wusste Router, also müssen Sie ihre Vaterkomponente rendern.

MJ Sameri
quelle
2

Mach es einfach:

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

und nicht vergessen: import { BrowserRouter } from "react-router-dom";

Ivan Carrasco Quiroz
quelle
1

Ich habe diesen Fehler erhalten, weil ich eine wiederverwendbare Komponente aus einer npm-Bibliothek importiert habe und die Versionen von react-router-domnicht übereinstimmten.

Stellen Sie also sicher, dass Sie an beiden Stellen dieselbe Version verwenden!

vaskort
quelle
0

Schreiben Sie den Router anstelle von Main in Render (letzte Zeile im Code). Gefällt mir ReactDOM.render (Router, document.getElementById ('root'));

Prakhar Mittal
quelle
0

Sie können die Link-Komponente in die Router-Komponente einfügen. Etwas wie das:

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

Wenn Sie nicht viel ändern möchten, verwenden Sie den folgenden Code in der onClick () -Methode.

this.props.history.push('/');
PRADEEP YADAV
quelle