Navigare a livello di codice utilizzando il router di risposta

Con react-router posso usare l’elemento Link per creare collegamenti nativamente gestiti da react router.

Vedo internamente che chiama this.context.transitionTo(...) .

Voglio fare una navigazione, ma non da un link, da una selezione a cascata per esempio. Come posso farlo in codice? Cos’è this.context ?

Ho visto il mixaggio di Navigation , ma posso farlo senza mixin?

React Router v4

Con v4 di React Router, ci sono tre approcci che è ansible adottare per il routing programmatico all’interno dei componenti.

  1. Utilizzare il componente di ordine superiore withRouter .
  2. Usa la composizione e rendi un
  3. Usa il context .

React Router è principalmente un wrapper attorno alla libreria della history . history gestisce l’interazione con window.history del browser per te con il suo browser e le sue cronologie hash. Fornisce anche una cronologia della memoria che è utile per gli ambienti che non hanno una cronologia globale. Ciò è particolarmente utile nello sviluppo di app per dispositivi mobili ( react-native ) e test di unità con Node.

Un’istanza di history ha due metodi per la navigazione: push e replace . Se si pensa alla history come a una serie di posizioni visitate, push aggiungerà una nuova posizione all’array e la replace sostituirà la posizione corrente nell’array con quella nuova. In genere si vorrà utilizzare il metodo push durante la navigazione.

Nelle versioni precedenti di React Router, era necessario creare la propria istanza della history , ma nella v4 i componenti , e per te istanze di browser, hash e memoria. React Router rende disponibili le proprietà e i metodi dell’istanza della history associata al router tramite il contesto, sotto l’object router .

1. Utilizzare il componente di ordine superiore withRouter

Il componente withRouter di ordine superiore withRouter l’object history come elemento prop del componente. Ciò consente di accedere ai metodi push e replace senza dover affrontare il context .

 import { withRouter } from 'react-router-dom' // this also works with react-router-native const Button = withRouter(({ history }) => (  )) 

2. Usa la composizione e rendi un

Il componente non è solo per le posizioni corrispondenti. È ansible eseguire il rendering di un percorso senza percorsi e corrisponderà sempre alla posizione corrente . Il componente passa gli stessi oggetti di scena di withRouter , quindi potrai accedere ai metodi della history attraverso il puntello della history .

 import { Route } from 'react-router-dom' const Button = () => (  (  )} /> ) 

3. Usa il contesto *

* Ma probabilmente non dovresti

L’ultima opzione è quella che dovresti usare solo se ti senti a tuo agio a lavorare con il modello di contesto di React. Sebbene il contesto sia un’opzione, è necessario sottolineare che il contesto è un’API instabile e React ha una sezione Perché non usare il contesto nella propria documentazione. Quindi usa a tuo rischio!

 const Button = (props, context) => (  ) // 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 e 2 sono le scelte più semplici da implementare, quindi per la maggior parte dei casi d’uso sono le tue migliori scommesse.

React-Router 4.0.0+ Risposta

In 4.0 e versioni successive, utilizza la cronologia come elemento prop del componente.

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

React-Router 3.0.0+ Risposta

In 3.0 e versioni successive, utilizzare il router come supporto per il componente.

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

React-Router 2.4.0+ Risposta

In 2.4 e versioni successive, utilizzare un componente di ordine superiore per ottenere il router come supporto del componente.

 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+ Risposta

Questa versione è retrocompatibile con 1.x quindi non c’è bisogno di una Guida all’aggiornamento. Basta esaminare gli esempi dovrebbe essere abbastanza buono.

Detto questo, se desideri passare al nuovo modello, c’è un modulo browserHistory all’interno del router a cui puoi accedere

import { browserHistory } from 'react-router'

Ora hai accesso alla cronologia del browser, quindi puoi fare cose come push, replace, ecc … Come:

browserHistory.push('/some/path')

Ulteriori letture: storie e navigazione


React-Router 1.xx Risposta

Non approfondirò i dettagli. Puoi leggere a riguardo nella Guida all’aggiornamento

Il cambiamento principale sulla domanda qui è il passaggio da Navigation mixin a History. Ora sta usando la cronologia del browser API per cambiare rotta, quindi useremo pushState() d’ora in poi.

Ecco un esempio utilizzando Mixin:

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

Nota che questa History proviene dal progetto rackt / storia . Non da React-Router stesso.

Se non si desidera utilizzare Mixin per qualche motivo (forse a causa della class ES6), è ansible accedere alla cronologia this.props.history dal router da this.props.history . Sarà accessibile solo per i componenti renderizzati dal tuo router. Quindi, se si desidera utilizzarlo in qualsiasi componente figlio, è necessario passarlo come attributo tramite props .

Puoi leggere di più sulla nuova versione alla loro documentazione 1.0.x.

Ecco una pagina di aiuto specifica sulla navigazione al di fuori del tuo componente

Si consiglia di afferrare una history = createHistory() riferimento history = createHistory() e chiamando replaceState su quello.

Risposta React-Router 0.13.x

Ho avuto lo stesso problema e sono riuscito a trovare la soluzione solo con il mixaggio di navigazione fornito con react-router.

Ecco come l’ho fatto

 import React from 'react'; import {Navigation} from 'react-router'; let Authentication = React.createClass({ mixins: [Navigation], handleClick(e) { e.preventDefault(); this.transitionTo('/'); }, render(){ return (
Click me!
); } });

Sono stato in grado di chiamare transitionTo() senza la necessità di accedere a .context

Oppure puoi provare la fantastica class ES6

 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 (
Click me!
); } } Authentication.contextTypes = { router: React.PropTypes.func.isRequired };

React-Router-Redux

Nota: se stai usando Redux, c’è un altro progetto chiamato React-Router-Redux che ti offre redux binding per ReactRouter, usando in qualche modo lo stesso approccio che fa React-Redux

React-Router-Redux ha alcuni metodi disponibili che consentono una semplice navigazione all’interno dei creatori di azioni. Questi possono essere particolarmente utili per le persone che hanno un’architettura esistente in React Native e desiderano utilizzare gli stessi pattern in React Web con un overhead minimo di boilerplate.

Esplora i seguenti metodi:

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

Ecco un esempio di utilizzo, con Redux-Thunk :

./actioncreators.js

 import { goBack } from 'react-router-redux' export const onBackPress = () => (dispatch) => dispatch(goBack()) 

./viewcomponent.js

  

React-Router v2

Per la versione più recente ( v2.0.0-rc5 ), il metodo di navigazione consigliato è quello di passare direttamente al singleton della cronologia. Puoi vederlo in azione nel documento Navigazione al di fuori dei componenti .

Estratto pertinente:

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

Se si utilizza la più recente API react-router, è necessario fare uso della history da this.props quando si è all’interno dei componenti:

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

Offre anche pushState ma è deprecato per gli avvisi registrati.

Se si utilizza react-router-redux , offre una funzione push è ansible inviare in questo modo:

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

Tuttavia, questo può essere usato solo per cambiare l’URL, non per navigare effettivamente nella pagina.

Ecco come farlo con react-router v2.0.0 con ES6 . react-router è allontanato dai mixin.

 import React from 'react'; export default class MyComponent extends React.Component { navigateToPage = () => { this.context.router.push('/my-route') }; render() { return (  ); } } MyComponent.contextTypes = { router: React.PropTypes.object.isRequired } 

Per questo, chi non controlla il lato server e per questo sta usando il router hash v2:

Inserisci la tua cronologia in un file separato (ad es. App_history.js ES6):

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

E usalo ovunque!

Il tuo punto di ingresso per 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((  ...  ), document.querySelector('[data-role="app"]')); 

La tua navigazione all’interno di qualsiasi componente (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() } }) 

Risposta 4.x di React-Router:

Da parte mia, mi piace avere un singolo object di cronologia che posso portare anche fuori dai componenti. Quello che mi piace fare è avere un singolo file history.js che imposto a richiesta, e semplicemente manipolarlo.

Devi solo cambiare BrowserRouter su Router e specificare la storia. Questo non cambia nulla per te tranne che hai il tuo object storico che puoi manipolare come vuoi.

È necessario installare la cronologia , la libreria utilizzata da react-router .

Esempio di utilizzo, notazione ES6:

history.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 Previous; } } 

EDIT 16 aprile 2018:

Se devi navigare da un componente che è effettivamente renderizzato da un componente Route , puoi anche accedere alla cronologia da oggetti di scena, in questo modo:

BasicComponent.js

 import React, { Component } from 'react'; class BasicComponent extends Component { navigate(e){ e.preventDefault(); this.props.history.push('/url'); } render(){ return Previous; } } 

Attenzione: questa risposta copre solo le versioni di ReactRouter precedenti alla 1.0

Aggiornerò questa risposta con i casi d’uso 1.0.0-rc1 dopo!

Puoi farlo anche senza mixin.

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

Il gotcha con i contesti è che non è accessibile a meno che non si definiscano i contextTypes sulla class.

Per quanto riguarda il contesto, è un object, come oggetti di scena, che viene passato da genitore a figlio, ma viene trasmesso implicitamente, senza dover ripetere ogni volta gli oggetti di scena. Vedi https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html

Ho provato almeno 10 modi per farlo prima che qualcosa funzionasse correttamente!

@Felipe Skinner’s withRouter answer è stato un po ‘travolgente per me, e non ero sicuro di voler creare nuovi nomi di class “ExportedWithRouter”.

Ecco il modo più semplice e pulito per farlo, circa corrente React-Router 3.0.0 ed ES6:

React-Router 3.xx con 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); 

oppure, se non è la tua class predefinita, esporta come:

 withRouter(Example); export { Example }; 

Nota che in 3.xx, il componente stesso utilizza router.push , quindi puoi passarlo qualsiasi cosa tu passi al tag, come:

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

Per i componenti ES6 + React, la soluzione seguente ha funzionato per me.

Ho seguito Felippe Skinner, ma ho aggiunto una soluzione end-to-end per aiutare i principianti come me.

Di seguito sono le versioni che ho usato:

“react-router”: “^ 2.7.0”

“reactjs”: “^ 15.3.1”

Di seguito è riportato il mio componente reattivo in cui ho utilizzato la navigazione programmatica utilizzando react-router:

 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 
// skipping html code
; } }; loginComp.contextTypes = { router: React.PropTypes.object.isRequired } module.exports = loginComp;

Di seguito è la configurazione per il mio router:

  import { Router, Route, IndexRedirect, browserHistory } from 'react-router' render(        , document.getElementById('root')); 

Per fare la navigazione a livello di programmazione, devi spingere una nuova cronologia per props.history nel tuo component , quindi qualcosa del genere può fare il lavoro per te:

 //using ES6 import React from 'react'; class App extends React.Component { constructor(props) { super(props) this.handleClick = this.handleClick.bind(this) } handleClick(e) { e.preventDefault() /* Look at here, you can add it here */ this.props.history.push('/redirected'); } render() { return ( 
) } } export default App;

Potrebbe non essere l’approccio migliore ma … Utilizzando react-router v4, il seguente typescript potrebbe dare un’idea per alcuni.

Nel componente visualizzato di seguito, ad esempio LoginPage , l’object router è accessibile e basta chiamare router.transitionTo('/homepage') per navigare.

Il codice di navigazione è stato preso da https://reac-router.now.sh/Match .

"react-router": "^4.0.0-2", "react": "^15.3.1",

 import Router from 'react-router/BrowserRouter'; import { History } from 'react-history/BrowserHistory'; import createHistory from 'history/createBrowserHistory'; const history = createHistory(); interface MatchWithPropsInterface { component: typeof React.Component, router: Router, history: History, exactly?: any, pattern: string } class MatchWithProps extends React.Component { render() { return(  ( React.createElement(this.props.component, this.props) )} /> ) } } ReactDOM.render(  {({ router }) => ( 
)}
, document.getElementById('app') );

React Router V4

tl: dr;

 if (navigate) { return  } 

La risposta semplice e dichiarativa è che devi usare in combinazione con setState()

push: boolean – quando true, il reindirizzamento spinge una nuova voce nella cronologia invece di sostituire quella corrente.


 import { Redirect } from 'react-router' class FooBar extends React.Component { state = { navigate: false } render() { const { navigate } = this.state // here is the important part if (navigate) { return  } // ^^^^^^^^^^^^^^^^^^^^^^^ return ( 
) } }

Esempio completo qui . Leggi di più qui .

PS. L’esempio utilizza gli inizializzatori di proprietà ES7 + per inizializzare lo stato. Guarda anche qui , se sei interessato.

In React-Router v4 ed ES6

Puoi usare withRouter e this.props.history.push .

 import {withRouter} from 'react-router-dom'; class Home extends Component { componentDidMount() { this.props.history.push('/redirect-to'); } } export default withRouter(Home); 

in base alla risposta precedente
da José Antonio Postigo e Ben Wheeler
la novità? deve essere scritto in Typescript
e l’uso di decoratori
OR proprietà / campo statici

 import * as React from "react"; import Component = React.Component; import { withRouter } from "react-router"; export interface INavigatorProps { router?: ReactRouter.History.History; } /** * Note: goes great with mobx * @inject("something") @withRouter @observer */ @withRouter export class Navigator extends Component{ navigate: (to: string) => void; constructor(props: INavigatorProps) { super(props); let self = this; this.navigate = (to) => self.props.router.push(to); } render() { return ( 
  • this.navigate("/home")}> Home
  • this.navigate("/about")}> About
) } } /** * Non decorated */ export class Navigator2 extends Component
{ static contextTypes = { router: React.PropTypes.object.isRequired, }; navigate: (to: string) => void; constructor(props: INavigatorProps, context: any) { super(props, context); let s = this; this.navigate = (to) => s.context.router.push(to); } render() { return (
  • this.navigate("/home")}> Home
  • this.navigate("/about")}> About
) } }

con qualunque npm installato oggi. “react-router”: “^ 3.0.0” e
“@ types / react-router”: “^ 2.0.41”

con React-Router v4 all’orizzonte, ora c’è un nuovo modo di farlo.

 import { MemoryRouter, BrowserRouter } from 'react-router'; const navigator = global && global.navigator && global.navigator.userAgent; const hasWindow = typeof window !== 'undefined'; const isBrowser = typeof navigator !== 'undefined' && navigator.indexOf('Node.js') === -1; const Router = isBrowser ? BrowserRouter : MemoryRouter;  

react-lego è un’app di esempio che mostra come utilizzare / aggiornare react-router e include esempi di test funzionali che consentono di navigare nell’app.

Con la versione corrente di React (15.3), this.props.history.push('/location'); ha funzionato per me, ma ha mostrato il seguente avviso:

browser.js: 49 Attenzione: [react-router] props.history e context.history sono deprecati. Si prega di utilizzare context.router .

e l’ho risolto usando context.router questo modo:

 import React from 'react'; class MyComponent extends React.Component { constructor(props) { super(props); this.backPressed = this.backPressed.bind(this); } backPressed() { this.context.router.push('/back-location'); } ... } MyComponent.contextTypes = { router: React.PropTypes.object.isRequired }; export default MyComponent; 

Se stai usando l’hash o la cronologia del browser, puoi farlo

 hashHistory.push('/login'); browserHistory.push('/login'); 

Per usare withRouter con un componente basato sulla class, prova qualcosa di simile qui sotto. Non dimenticare di modificare la dichiarazione di esportazione da utilizzare withRouter :

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

 class YourClass extends React.Component { yourFunction = () => { doSomeAsyncAction(() => this.props.history.push('/other_location') ) } render() { return ( 
) } } export default withRouter(YourClass);

React-Router V4

se stai usando la versione 4, puoi usare la mia libreria (plug Shameless) in cui devi semplicemente inviare un’azione e tutto funziona!

 dispatch(navigateTo("/aboutUs")); 

https://www.npmjs.com/package/trippler

La risposta giusta era per me al momento della scrittura

 this.context.router.history.push('/'); 

Ma è necessario aggiungere PropTypes al componente

 Header.contextTypes = { router: PropTypes.object.isRequired } export default Header; 

Non dimenticare di importare PropTypes

 import PropTypes from 'prop-types'; 

Forse non è la soluzione migliore ma fa il lavoro:

 import { Link } from 'react-router-dom'; // create functional component Post export default Post = () => ( 
);

Fondamentalmente, una logica legata a un’azione (in questo caso una cancellazione di un post) finirà per chiamare un trigger per il reindirizzamento. Questo non è l’ideale, perché aggiungerai un trigger del nodo DOM al tuo markup solo così puoi chiamarlo comodamente quando necessario. Inoltre, interagirai direttamente con il DOM, che in un componente React potrebbe non essere desiderato.

Tuttavia, questo tipo di reindirizzamento non è richiesto spesso. Quindi uno o due extra, collegamenti nascosti nel markup del componente non farebbero male così tanto, soprattutto se dai loro nomi significativi.

If happen to pair RR4 w/ redux through react-router-redux , use the routing action creators from react-router-redux is a option as well.

 import { push, replace, ... } from 'react-router-redux' class WrappedComponent extends React.Component { handleRedirect(url, replaceState = true) { replaceState ? this.props.dispatch(replace(url)) : this.props.dispatch(push(url)) } render() { ... } } export default connect(null)(WrappedComponent) 

If use redux thunk/saga to manage async flow, import the above action creators in redux actions and hook to react components using mapDispatchToProps might be better.

Please find below working code: It is very simple method to navigate using react Router:

 class Register extends React.Component { state = { toDashboard: false, } handleSubmit = (user) => { saveUser(user) .then(() => this.setState(() => ({ toDashboard: true }))) } render() { if (this.state.toDashboard === true) { return  } return ( 

Register

) } }

< Redirect /> is

Composable ✅ Declarative ✅ user event -> state change -> re-render ✅

Register component is being rendered by React Router, our code could look like this

 class Register extends React.Component { handleSubmit = (user) => { saveUser(user).then(() => this.props.history.push('/dashboard') )) } render() { return ( 

Register

) } }

by adding withRouter, it would look like this

 import { withRouter } from 'react-router-dom' class Register extends React.Component { handleSubmit = (user) => { saveUser(user).then(() => this.props.history.push('/dashboard') )) } render() { return ( 

Register

) } } export default withRouter(Register)

There are two ways to programmatically navigate with React Router – and history.push. Which you use is mostly up to you and your specific use case, though I try to favor Redirect.

In react router v4. I follow this two way to route programmatically.

 1. this.props.history.push("/something/something") 2. this.props.history.replace("/something/something") 

Number two

Replaces the current entry on the history stack

To get history in props you may have to wrap your component with

withRouter https://reacttraining.com/react-router/core/api/withRouter

Simply just use this.props.history.push('/where/to/go');