Frage Programmgesteuertes Navigieren mit react router


Mit react-router Ich kann das benutzen Link Element zum Erstellen von Links, die nativ vom reaktiven Router behandelt werden.

Ich sehe intern, dass es ruft this.context.transitionTo(...).

Ich möchte eine Navigation durchführen, aber nicht von einem Link, z. B. von einer Dropdown-Auswahl. Wie kann ich das im Code tun? Was ist this.context?

Ich sah Navigation Mixin, aber kann ich das ohne Mixins machen?


775
2018-06-26 17:38


Ursprung


Antworten:


Reagieren Router v4

Mit v4 von React Router gibt es drei Ansätze, die Sie zum programmatischen Routing innerhalb von Komponenten verwenden können.

  1. Benutze die withRouter Komponente höherer Ordnung.
  2. Verwenden Sie die Komposition und rendern Sie a <Route>
  3. Benutze die context.

React Router ist meist ein Wrapper um die history Bibliothek. history behandelt die Interaktion mit dem Browser window.history für Sie mit seinem Browser und Hash-Historien. Es bietet auch eine Speicherhistorie, die für Umgebungen ohne globale Historie nützlich ist. Dies ist besonders nützlich bei der Entwicklung von mobilen Apps (react-native) und Komponententests mit Node.

EIN history Instanz verfügt über zwei Methoden zum Navigieren: push und replace. Wenn du an das denkst history als eine Reihe von besuchten Orten, push fügt dem Array einen neuen Speicherort hinzu und replace ersetzt den aktuellen Standort im Array durch den neuen. Normalerweise möchten Sie die push Methode, wenn Sie navigieren.

In früheren Versionen von React Router mussten Sie Ihre eigenen erstellen history Beispiel, aber in v4 der <BrowserRouter>, <HashRouter>, und <MemoryRouter> Komponenten erstellen Browser-, Hash- und Speicherinstanzen für Sie. React Router macht die Eigenschaften und Methoden des history Instanz, die mit Ihrem Router über den Kontext verfügbar ist router Objekt.

1. Verwenden Sie die withRouter Komponente höherer Ordnung

Das withRouter Komponente höherer Ordnung wird die injizieren history Objekt als eine Stütze der Komponente. Dies ermöglicht Ihnen den Zugriff auf die push und replace Methoden ohne sich mit dem zu beschäftigen context.

import { withRouter } from 'react-router-dom'
// this also works with react-router-native

const Button = withRouter(({ history }) => (
  <button
    type='button'
    onClick={() => { history.push('/new-location') }}
  >
    Click Me!
  </button>
))

2. Verwenden Sie die Komposition und rendern Sie a <Route>

Das <Route> Komponente ist nicht nur für übereinstimmende Standorte. Sie können eine weglose Route rendern und Es passt immer zum aktuellen Standort. Das <Route> Komponente übergibt die gleichen Requisiten wie withRouter, so können Sie auf die zugreifen history Methoden durch die history Stütze.

import { Route } from 'react-router-dom'

const Button = () => (
  <Route render={({ history}) => (
    <button
      type='button'
      onClick={() => { history.push('/new-location') }}
    >
      Click Me!
    </button>
  )} />
)

3. Nutze den Kontext *

* Aber du solltest es wahrscheinlich nicht tun

Die letzte Option ist eine Option, die Sie nur verwenden sollten, wenn Sie sich bei der Arbeit mit Reacts wohl fühlen Kontext Modell. Obwohl Kontext eine Option ist, sollte betont werden, dass der Kontext eine instabile API ist und React über einen Abschnitt verfügt Warum nicht Kontext verwenden in ihrer Dokumentation. Also benutze es auf eigene Gefahr!

const Button = (props, context) => (
  <button
    type='button'
    onClick={() => {
      // context.history.push === history.push
      context.history.push('/new-location')
    }}
  >
    Click Me!
  </button>
)

// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  })
}

1 und 2 sind die einfachsten zu implementierenden Optionen, daher sind sie für die meisten Anwendungsfälle die besten Wetten.


614
2018-02-08 18:39



React-Router 4.0.0+ Antworten

Verwenden Sie in 4.0 und höher den Verlauf als Prop von Ihrer Komponente.

class Example extends React.Component {
   // use `this.props.history.push('/some/path')` here
};

React-Router 3.0.0+ Antworten

In 3.0 und höher, verwenden Sie den Router als eine Stütze Ihrer Komponente.

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

React-Router 2.4.0+ Antworten

Verwenden Sie in 2.4 und höher eine Komponente höherer Ordnung, um den Router als Prop von Ihrer Komponente zu erhalten.

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
var DecoratedExample = withRouter(Example);

// PropTypes
Example.propTypes = {
  router: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  }).isRequired
};

React-Router 2.0.0+ Antworten

Diese Version ist abwärtskompatibel zu 1.x, daher ist kein Upgrade-Handbuch erforderlich. Das Durchlaufen der Beispiele sollte gut genug sein.

Das heißt, wenn Sie zu dem neuen Muster wechseln möchten, gibt es ein browserHistory-Modul innerhalb des Routers, auf das Sie zugreifen können

import { browserHistory } from 'react-router'

Jetzt haben Sie Zugriff auf Ihren Browser-Verlauf, so dass Sie Dinge wie Push, Replace usw. tun können.

browserHistory.push('/some/path')

Weiterführende Literatur: Geschichten und Navigation


React-Router 1.x.x Antworten

Ich werde nicht auf Details upgraden. Sie können darüber in der lesen Upgrade-Anleitung

Die Hauptänderung an der Frage hier ist der Wechsel von Navigation Mixin zu Geschichte. Jetzt verwenden wir die BrowserhistoryAPI, um die Route zu ändern, die wir verwenden werden pushState() von jetzt an.

Hier ist ein Beispiel mit Mixin:

var Example = React.createClass({
  mixins: [ History ],
  navigateToHelpPage () {
    this.history.pushState(null, `/help`);
  }
})

Beachten Sie, dass dies History kommt von Rackt / Geschichte Projekt. Nicht von React-Router selbst.

Wenn Sie Mixin aus irgendeinem Grund nicht verwenden möchten (möglicherweise aufgrund der ES6-Klasse), können Sie auf den Verlauf zugreifen, den Sie vom Router erhalten this.props.history. Es ist nur für die von Ihrem Router gerenderten Komponenten zugänglich. Wenn Sie es in allen untergeordneten Komponenten verwenden möchten, müssen Sie es als Attribut übergeben props.

Sie können mehr über die neue Version in ihrem lesen 1.0.x Dokumentation

Hier ist eine Hilfeseite speziell zum Navigieren außerhalb Ihrer Komponente

Es empfiehlt, eine Referenz zu greifen history = createHistory() und anruft replaceState auf diesem.

React-Router 0.13.x Antworten

Ich bin auf das gleiche Problem gestoßen und konnte nur die Lösung mit dem Navigations-Mix finden, der mit react-router kommt.

Hier ist, wie ich es gemacht habe

import React from 'react';
import {Navigation} from 'react-router';

let Authentication = React.createClass({
  mixins: [Navigation],

  handleClick(e) {
    e.preventDefault();

    this.transitionTo('/');
  },

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

Ich konnte anrufen transitionTo() ohne die Notwendigkeit, darauf zuzugreifen .context

Oder Sie könnten die schicke ES6 ausprobieren class

import React from 'react';

export default class Authentication extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();

    this.context.router.transitionTo('/');
  }

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
}

Authentication.contextTypes = {
  router: React.PropTypes.func.isRequired
};

Reagieren-Router-Redux

Hinweis: Wenn Sie Redux verwenden, gibt es ein anderes Projekt namens    Reagieren-Router-Redux das gibt dir   Redux-Bindungen für ReactRouter, mit etwas der gleichen Vorgehensweise, die    Reagieren-Redux tut

React-Router-Redux verfügt über einige Methoden, mit denen Sie einfach aus den Aktions-Erstellern navigieren können. Dies kann besonders nützlich für Personen sein, die eine existierende Architektur in React Native haben, und sie möchten die gleichen Muster in React Web mit minimalem Standard-Overhead verwenden.

Erkunden Sie die folgenden Methoden:

  • push(location)
  • replace(location)
  • go(number)
  • goBack()
  • goForward()

Hier ist ein Beispiel für die Verwendung mit Redux-Thunk:

./actioncreators.js

import { goBack } from 'react-router-redux'

export const onBackPress = () => (dispatch) => dispatch(goBack())

./viewcomponent.js

<button
  disabled={submitting}
  className="cancel_button"
  onClick={(e) => {
    e.preventDefault()
    this.props.onBackPress()
  }}
>
  CANCEL
</button>

662
2018-06-26 17:49



Reagieren-Router v2

Für die neueste Version (v2.0.0-rc5), die empfohlene Navigationsmethode besteht darin, direkt auf den History Singleton zu drücken. Sie können das in Aktion in der sehen Navigieren außerhalb von Komponenten doc.

Relevanter Auszug:

import { browserHistory } from 'react-router';
browserHistory.push('/some/path');

Wenn Sie die neuere react-router-API verwenden, müssen Sie die historyvon this.props wenn innerhalb von Komponenten so:

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

Es bietet auch an pushState aber das ist veraltet pro protokollierte Warnungen.

Wenn Sie verwenden react-router-reduxes bietet a push Funktion können Sie wie folgt versenden:

import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));

Dies kann jedoch nur dazu verwendet werden, die URL zu ändern, um nicht zu der Seite zu navigieren.


466
2018-01-18 20:32



So machen Sie das mit react-router v2.0.0 mit ES6. react-router hat sich von Mixins entfernt.

import React from 'react';

export default class MyComponent extends React.Component {
  navigateToPage = () => {
    this.context.router.push('/my-route')
  };

  render() {
    return (
      <button onClick={this.navigateToPage}>Go!</button>
    );
  }
}

MyComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}

34
2018-01-22 20:46



Für diesen, der die Server-Seite nicht kontrolliert und deshalb den Hash-Router v2 benutzt:

Platzieren Sie Ihre Geschichte in eine separate Datei (z. B. app_history.js ES6):

import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });

export default appHistory;

Und benutze es überall!

Ihr Einstiegspunkt für den react-router (app.js ES6):

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Redirect } from 'react-router'
import appHistory from './app_history'
...
const render((
  <Router history={appHistory}>
  ...
  </Router>
), document.querySelector('[data-role="app"]'));

Ihre Navigation innerhalb einer Komponente (ES6):

import appHistory from '../app_history'
...
ajaxLogin('/login', (err, data) => {
  if (err) {
    console.error(err); // login failed
  } else {
    // logged in
    appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
  }
})

25
2018-03-19 12:59



React-Router 4.x Antwort:

An meinem Ende möchte ich ein einziges historisches Objekt haben, das ich auch außerhalb von Komponenten tragen kann. Was ich tun möchte, ist eine einzige Datei history.js zu haben, die ich bei Bedarf importiere und sie einfach manipuliere.

Du musst dich nur ändern BrowserRouter zu Router, und geben Sie die Verlaufsrequisite an. Dies ändert nichts für Sie, außer dass Sie Ihr eigenes Historienobjekt haben, das Sie beliebig manipulieren können.

Sie müssen installieren Geschichte, die von react-router.

Beispielverwendung, ES6-Notation:

Geschichte.js

import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()

BasicComponent.js

import React, { Component } from 'react';
import history from './history';

class BasicComponent extends Component {

    goToIndex(e){
        e.preventDefault();
        history.push('/');
    }

    render(){
        return <a href="#" onClick={this.goToIndex}>Previous</a>;
    }
}

EDIT 16. April 2018:

Wenn Sie von einer Komponente navigieren müssen, die tatsächlich von a gerendert wird Route Komponente, können Sie auch Zugriff auf Geschichte von Requisiten, wie folgt:

BasicComponent.js

import React, { Component } from 'react';

class BasicComponent extends Component {

    navigate(e){
        e.preventDefault();
        this.props.history.push('/url');
    }

    render(){
        return <a href="#" onClick={this.navigate}>Previous</a>;
    }
}

20
2018-06-06 22:14



Warnung: Diese Antwort deckt nur ReactRouter-Versionen vor 1.0 ab

Ich werde diese Antwort mit 1.0.0-rc1 Anwendungsfällen nach aktualisieren!

Sie können dies auch ohne Mixins tun.

let Authentication = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  handleClick(e) {
    e.preventDefault();
    this.context.router.transitionTo('/');
  },
  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

Das Problem mit Kontexten ist, dass es nicht zugänglich ist, es sei denn, Sie definieren das contextTypes auf die Klasse.

Was den Kontext angeht, ist es ein Objekt, wie Requisiten, die von Eltern zu Kind weitergegeben werden, aber es wird implizit weitergegeben, ohne jedes Mal Requisiten neu deklarieren zu müssen. Sehen https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html


19
2018-06-30 06:14



Ich habe mindestens 10 Möglichkeiten ausprobiert, bevor etwas richtig funktioniert hat!

@Felipe Skinner's withRouter Die Antwort war ein bisschen überwältigend für mich, und ich war mir nicht sicher, ob ich neue "ExportedWithRouter" Klassennamen machen wollte.

Hier ist der einfachste und sauberste Weg, um es zu tun, etwa aktuelle React-Router 3.0.0 und ES6:

React-Router 3.x.x mit ES6:

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
export default withRouter(Example);

oder, wenn es nicht Ihre Standardklasse ist, exportieren Sie wie folgt:

withRouter(Example);
export { Example };

Beachten Sie, dass in 3.x.x die <Link> Komponente selbst verwendet router.push, also kannst du alles passieren, was du passierst <Link to= Tag, wie:

   this.props.router.push({pathname: '/some/path', query: {key1: 'val1', key2: 'val2'})'

15
2017-11-30 14:02



Für ES6 + React-Komponenten funktionierte die folgende Lösung für mich.

Ich folgte Felippe Skinner, fügte aber eine End-to-End-Lösung hinzu, um Anfängern wie mir zu helfen.

Im Folgenden sind die Versionen, die ich verwendet habe:

"react-router": "^ 2.7.0"

"Reagieren": "15.3.1"

Unten ist meine reaktive Komponente, wo ich die programmatische Navigation mit react-router benutzt habe:

import React from 'react';

class loginComp extends React.Component {
   constructor( context) {
    super(context);
    this.state = {
      uname: '',
      pwd: ''
    };
  }

  redirectToMainPage(){
        this.context.router.replace('/home');
  }

  render(){
    return <div>
           // skipping html code 
             <button onClick={this.redirectToMainPage.bind(this)}>Redirect</button>
    </div>;
  }
};

 loginComp.contextTypes = {
    router: React.PropTypes.object.isRequired
 }

 module.exports = loginComp;

Unten ist die Konfiguration für meinen Router:

 import { Router, Route, IndexRedirect, browserHistory } from 'react-router'

 render(<Router history={browserHistory}>
          <Route path='/' component={ParentComp}>
            <IndexRedirect to = "/login"/>
            <Route path='/login' component={LoginComp}/>
            <Route path='/home' component={HomeComp}/>
            <Route path='/repair' component={RepairJobComp} />
            <Route path='/service' component={ServiceJobComp} />
          </Route>
        </Router>, document.getElementById('root'));

11
2017-09-12 22:00