web-dev-qa-db-fra.com

Naviguer par programme en utilisant le routeur de réaction

Avec react-router, je peux utiliser l'élément Link pour créer des liens qui sont gérés de manière native par le routeur de réaction.

Je vois en interne qu'il appelle this.context.transitionTo(...).

Je veux faire une navigation, mais pas à partir d'un lien, à partir d'une sélection déroulante par exemple. Comment puis-je faire cela dans le code? Qu'est-ce que this.context?

J'ai vu le mixin Navigation, mais puis-je le faire sans mixins?

1159
George Mauer

React Router v4

Avec v4 of React Router, il existe trois approches possibles pour le routage par programmation au sein des composants.

  1. Utilisez le composant withRouter d'ordre supérieur.
  2. Utiliser la composition et rendre un _<Route>_
  3. Utilisez le context.

React Router est principalement un wrapper autour de la bibliothèque history . history gère les interactions avec le navigateur window.history avec son navigateur et ses historiques de hachage. Il fournit également un historique de la mémoire utile pour les environnements qui n’ont pas d’historique global. Ceci est particulièrement utile pour le développement d'applications mobiles (_react-native_) et les tests unitaires avec Node.

Une instance history a deux méthodes de navigation: Push et replace. Si vous pensez que history est un tableau d'emplacements visités, Push ajoutera un nouvel emplacement au tableau et replace remplacera l'emplacement actuel du tableau par le nouveau. Généralement, vous souhaiterez utiliser la méthode Push lorsque vous naviguez.

Dans les versions antérieures de React Router, vous deviez créer votre propre instance history, mais dans la v4, les composants _<BrowserRouter>_, _<HashRouter>_ et _<MemoryRouter>_ créeraient un navigateur. hash et instances de mémoire pour vous. React Router rend disponibles les propriétés et les méthodes de l'instance history associée à votre routeur par le biais du contexte, sous l'objet router.

1. Utilisez le composant withRouter d'ordre supérieur

Le composant d'ordre supérieur withRouter injectera l'objet history en tant qu'accessoire du composant. Cela vous permet d'accéder aux méthodes Push et replace sans avoir à vous occuper de 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. Utilisez la composition et rendez un _<Route>_

Le composant _<Route>_ ne se limite pas aux emplacements correspondants. Vous pouvez rendre un itinéraire sans chemin et il correspondra toujours à l'emplacement actuel . Le composant _<Route>_ transmet les mêmes accessoires que withRouter. Vous pourrez ainsi accéder aux méthodes history par le biais de history prop.

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

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

3. Utilisez le contexte *

Mais vous ne devriez probablement pas

La dernière option est celle que vous ne devriez utiliser que si vous vous sentez à l'aise avec le modèle contexte de React. Bien que le contexte soit une option, il convient de souligner que le contexte est une API instable et que React a une section Pourquoi ne pas utiliser le contexte dans sa documentation. Alors utilisez à vos risques et périls!

_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 et 2 sont les choix les plus simples à mettre en œuvre. Par conséquent, dans la plupart des cas, ce sont vos meilleurs choix.

1042
Paul S

React-Router 4.0.0 + Réponse

Dans les versions 4.0 et supérieures, utilisez l'historique comme accessoire de votre composant.

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

Remarque: this.props.history n'existe pas dans le cas où votre composant n'a pas été rendu par <Route>. Vous devez utiliser <Route path="..." component={YourComponent}/> pour avoir this.props.history dans YourComponent

React-Router 3.0.0 + Réponse

Dans les versions 3.0 et supérieures, utilisez le routeur comme accessoire de votre composant.

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

React-Router 2.4.0 + Réponse

Dans les versions 2.4 et supérieures, utilisez un composant d'ordre supérieur pour obtenir le routeur comme accessoire de votre composant.

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 + Réponse

Cette version est rétro-compatible avec 1.x, vous n'avez donc pas besoin d'un Guide de mise à niveau. Il suffit de passer en revue les exemples.

Cela dit, si vous souhaitez passer au nouveau modèle, il existe un module browserHistory dans le routeur auquel vous pouvez accéder avec

import { browserHistory } from 'react-router'

Maintenant, vous avez accès à l'historique de votre navigateur, vous pouvez donc faire des choses comme Push, remplacer, etc.

browserHistory.Push('/some/path')

Lectures supplémentaires: Histoires et Navigation


React-Router 1.x.x Réponse

Je n'entrerai pas dans les détails de la mise à niveau. Vous pouvez lire à ce sujet dans le Guide de mise à nivea

Le principal changement concernant la question ici est le passage du mixage Navigation à l’historique. Maintenant, il utilise historyAPI dans le navigateur pour changer de route. Nous allons donc utiliser pushState() à partir de maintenant.

Voici un exemple utilisant Mixin:

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

Notez que cette History provient de rackt/history project. Pas de React-Router lui-même.

Si vous ne souhaitez pas utiliser Mixin pour une raison quelconque (peut-être à cause de la classe ES6), vous pouvez accéder à l'historique que vous obtenez du routeur à partir de this.props.history. Il ne sera accessible que pour les composants rendus par votre routeur. Donc, si vous voulez l’utiliser dans n’importe quel composant enfant, il doit être transmis comme attribut via props.

Vous pouvez en savoir plus sur la nouvelle version à leur documentation 1.0.x

Voici ne page d’aide spécifiquement consacrée à la navigation en dehors de votre composant

Il est recommandé de saisir une référence history = createHistory() et d’appeler replaceState dessus.

React-Router 0.13.x Réponse

J'ai eu le même problème et je n'ai trouvé que la solution avec le mix de navigation fourni avec react-router.

Voici comment je l'ai fait

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

J'ai pu appeler transitionTo() sans avoir besoin d'accéder à .context

Ou vous pouvez essayer la fantaisie ES6 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
};

React-Router-Redux

Remarque: si vous utilisez Redux, il existe un autre projet appelé React-Router-Redux qui vous fournit des liaisons redux pour ReactRouter, en utilisant à peu près la même approche que React-Redux

React-Router-Redux dispose de quelques méthodes permettant une navigation simple depuis les créateurs d’actions internes. Celles-ci peuvent être particulièrement utiles pour les personnes qui ont une architecture existante dans React Native et souhaitent utiliser les mêmes modèles dans React Web avec un minimum de temps système.

Explorez les méthodes suivantes:

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

Voici un exemple d'utilisation, avec 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>
828
Felipe Skinner

React-Router v2

Pour la version la plus récente (v2.0.0-rc5), la méthode de navigation recommandée consiste à appuyer directement sur le singleton d'historique. Vous pouvez voir cela en action dans le = Navigation en dehors de la documentation sur les composants .

Extrait pertinent:

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

Si vous utilisez la nouvelle API react-router, vous devez utiliser le history de this.props lorsque vous vous trouvez dans des composants, par exemple:

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

Il propose également pushState mais il est déconseillé pour les avertissements enregistrés.

Si vous utilisez react-router-redux, il offre une fonction Push que vous pouvez envoyer comme suit:

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

Toutefois, cela peut uniquement être utilisé pour modifier l'URL, pas pour accéder à la page.

492
Bobby

Voici comment procéder avec react-router v2.0.0 avec ES6 . _react-router_ s'est éloigné des mixins.

_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
}
_
49
Alex Miller

React-Router 4.x Réponse:

De mon côté, j'aime bien n'avoir qu'un seul objet d'historique que je puisse porter, même en dehors des composants. Ce que j'aime faire, c’est d’avoir un seul fichier history.js que je peux importer à la demande et de le manipuler.

Il vous suffit de changer BrowserRouter en Routeur et de spécifier l'historique prop. Cela ne change rien pour vous si ce n'est que vous avez votre propre objet d'historique que vous pouvez manipuler à votre guise.

Vous devez installer history , la bibliothèque utilisée par react-router.

Exemple d'utilisation, notation 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 <a href="#" onClick={this.goToIndex}>Previous</a>;
    }
}

EDIT 16 avril 2018:

Si vous devez naviguer à partir d'un composant qui est réellement rendu à partir d'un composant Route, vous pouvez également accéder à l'historique à partir d'accessoires, comme ceci:

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>;
    }
}
37
Eric Martin

Pour celui-ci, qui ne contrôle pas le côté serveur et utilise pour cette raison le routeur de hachage v2:

Placez votre historique dans un fichier séparé (par exemple, app_history.js ES6):

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

export default appHistory;

Et utilisez-le partout!

Votre point d'entrée pour 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"]'));

Votre navigation dans n'importe quel composant (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()
  }
})
35
Alexey Volodko

React Router V4

tl: dr;

if (navigate) {
  return <Redirect to="/" Push={true} />
}

La réponse simple et déclarative est que vous devez utiliser <Redirect to={URL} Push={boolean} /> en combinaison avec setState()

Push: boolean - lorsque la valeur est true, la redirection insère une nouvelle entrée dans l'historique au lieu de remplacer celle en cours.


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 <Redirect to="/" Push={true} />
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^

    return (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}

Exemple complet ici . Lire la suite ici .

PS. L'exemple utilise initialiseurs de propriété ES7 + pour initialiser l'état. Regardez ici aussi, si cela vous intéresse.

30
Lyubomir

Attention: cette réponse couvre uniquement les versions de ReactRouter antérieures à 1.0

Je mettrai à jour cette réponse avec les cas d'utilisation 1.0.0-rc1 après!

Vous pouvez le faire sans mixins aussi.

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

Le problème avec les contextes est qu'il n'est accessible que si vous définissez la contextTypes sur la classe.

En ce qui concerne le contexte, il s’agit d’un objet, comme les accessoires, qui sont transmis de parent à enfant, mais de manière implicite, sans avoir à redéclarer les accessoires à chaque fois. Voir https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html

26
Qiming

J'ai essayé au moins 10 façons de faire cela avant que quelque chose fonctionne correctement!

La réponse de withRouter de @Felipe Skinner a été un peu accablante pour moi, et je n'étais pas sûre de vouloir créer de nouveaux noms de classe "ExportedWithRouter".

Voici le moyen le plus simple et le plus propre de le faire, à peu près actuel, React-Router 3.0.0 et ES6:

React-Router 3.x.x avec 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);

ou, si ce n'est pas votre classe par défaut, exportez comme ceci:

withRouter(Example);
export { Example };

Notez que dans 3.x.x, le composant <Link> utilise lui-même router.Push, de sorte que vous pouvez le transmettre comme vous le feriez avec la balise <Link to=, comme ceci:

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

Pour faire la navigation par programmation, vous devez envoyer un nouveau historique au props.history dans votre component, afin que ce type de travail puisse faire le travail à votre place. :

//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 (
      <div>
        <button onClick={this.handleClick}>
          Redirect!!!
        </button>
      </div>
    )
  }
}

export default App;
19
Alireza

Pour les composants ES6 + React, la solution suivante a fonctionné pour moi.

J'ai suivi Felippe skinner, mais j'ai ajouté une solution de bout en bout pour aider les débutants comme moi.

Voici les versions que j'ai utilisées:

"react-router": "^ 2.7.0"

"réagir": "^ 15.3.1"

Ci-dessous se trouve mon composant de réaction où j'ai utilisé la navigation programmatique à l’aide de réacteur-routeur:

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;

Ci-dessous la configuration de mon routeur:

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

Veuillez trouver ci-dessous le code de travail: Comme indiqué dans cet article , il est très simple de naviguer à l'aide de 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 <Redirect to='/dashboard' />
    }

    return (
      <div>
        <h1>Register</h1>
        <Form onSubmit={this.handleSubmit} />
      </div>
    )
  }
}

< Redirect /> est

Composable ✅ Déclaratif event événement utilisateur -> changement d'état -> re-rendu

Le composant Register est rendu par le routeur React, notre code pourrait ressembler à ceci

class Register extends React.Component {
  handleSubmit = (user) => {
    saveUser(user).then(() =>
      this.props.history.Push('/dashboard')
    ))
  }
  render() {
    return (
      <div>
        <h1>Register</h1>
        <Form onSubmit={this.handleSubmit} />
      </div>
    )
  }
}

en ajoutant withRouter, cela ressemblerait à ceci

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

class Register extends React.Component {
  handleSubmit = (user) => {
    saveUser(user).then(() =>
      this.props.history.Push('/dashboard')
    ))
  }
  render() {
    return (
      <div>
        <h1>Register</h1>
        <Form onSubmit={this.handleSubmit} />
      </div>
    )
  }
}

export default withRouter(Register)

Il existe deux manières de naviguer par programme avec React Router - et history.Push. Ce que vous utilisez dépend principalement de vous et de votre cas d'utilisation spécifique, bien que j'essaie de privilégier la redirection.

16
kiran malvi

Ce n'est peut-être pas la meilleure approche mais ... À l'aide de react-router v4, le TypeScript suivant pourrait en donner une idée.

Dans le composant rendu ci-dessous, par ex. LoginPage, router l'objet est accessible et il suffit d'appeler router.transitionTo('/homepage') pour naviguer.

Le code de navigation a été pris de .

"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<MatchWithPropsInterface,any> {
  render() {
    return(
      <Match {...this.props} render={(matchProps) => (
             React.createElement(this.props.component, this.props)

        )}
       />
    )
  }
}

ReactDOM.render(
    <Router>
      {({ router }) => (
        <div>
          <MatchWithProps exactly pattern="/" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/login" component={LoginPage} router={router} history={history} />
          <MatchWithProps pattern="/homepage" component={HomePage} router={router} history={history} />
          <Miss component={NotFoundView} />
        </div>
      )}
    </Router>,

   document.getElementById('app')
);
16
mcku

Dans React-Router v4 et ES6

Vous pouvez utiliser withRouter et 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);
15
Hossein

Pour utiliser withRouter avec un composant basé sur une classe, essayez l'une des solutions suivantes. N'oubliez pas de changer l'instruction d'exportation pour utiliser withRouter:

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

class YourClass extends React.Component {
  yourFunction = () => {
    doSomeAsyncAction(() =>
      this.props.history.Push('/other_location')
    )
  }

  render() {
    return (
      <div>
        <Form onSubmit={ this.yourFunction } />
      </div>
    )
  }
}

export default withRouter(YourClass);
13
Janos

Dans réagir routeur v4. Je suis cette double façon de route par programmation.

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

Numéro deux

Remplace l'entrée actuelle sur la pile d'historique

Pour obtenir l'historique dans les accessoires, vous devrez peut-être envelopper votre composant avec

avec routeur

10
saiful619945

basé sur la réponse précédente
de José Antonio Postigo et Ben Wheeler
la nouveauté? doit être écrit en TypeScript
et l'utilisation de décorateurs
OU statique propriété/champ

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<INavigatorProps, {}>{
    navigate: (to: string) => void;
    constructor(props: INavigatorProps) {
        super(props);
        let self = this;
        this.navigate = (to) => self.props.router.Push(to);
    }
    render() {
        return (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

/**
 * Non decorated 
 */
export class Navigator2 extends Component<INavigatorProps, {}> {

    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 (
            <ul>
                <li onClick={() => this.navigate("/home")}>
                    Home
                </li>
                <li onClick={() => this.navigate("/about")}>
                    About
                </li>
            </ul>
        )
    }
}

avec npm installé aujourd'hui. "react-router": "^ 3.0.0" et
"@ types/react-router": "^ 2.0.41"

10
Dan

avec React-Router v4 à l’horizon, il existe maintenant une nouvelle façon de procéder.

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;

<Router location="/page-to-go-to"/>

react-lego est un exemple d'application montrant comment utiliser/mettre à jour react-router et comprenant des exemples de tests fonctionnels permettant de naviguer dans l'application.

10
peter.mouland

Si vous utilisez l'historique du hachage ou du navigateur, vous pouvez le faire.

hashHistory.Push('/login');
browserHistory.Push('/login');
8
Zaman Afzal

Avec la version actuelle de React (15.3), this.props.history.Push('/location'); fonctionnait pour moi, mais il contenait l'avertissement suivant:

browser.js: 49 Avertissement: [react-router] props.history et context.history sont obsolètes. Veuillez utiliser context.router.

et je l'ai résolu en utilisant context.router comme ceci:

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

React-Router V4

si vous utilisez la version 4, vous pouvez utiliser ma bibliothèque (Shameless Plug) où vous envoyez simplement une action et tout fonctionne!

dispatch(navigateTo("/aboutUs"));

trippler

6
Garry Taylor

Ceux qui sont confrontés à des problèmes lors de l’implémentation de ceci sur react-router v4.

Voici une solution de travail pour naviguer dans l'application de réaction des actions redux.

histoire.js

import createHistory from 'history/createBrowserHistory'

export default createHistory()

App.js/Route.jsx

import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
 <Route path="/test" component={Test}/>
</Router>

another_file.js OR fichier redux

import history from './history' 

history.Push('/test') // this should change the url and re-render Test component

Tout cela grâce à ce commentaire: commentaire sur les problèmes de ReactTraining

5
reflexgravity

S'il arrive de coupler RR4 avec redux via react-router-redux , utilisez les créateurs d'action de routage de react-router-redux est également une option.

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)

Si vous utilisez redux thunk/saga pour gérer le flux async, importez les créateurs d'action ci-dessus dans les actions redux et connectez-vous pour réagir aux composants à l'aide de mapDispatchToProps peut être préférable.

4
Xlee

Ce n’est peut-être pas la meilleure solution, mais le travail est fait:

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

// create functional component Post
export default Post = () => (
    <div className="component post">

        <button className="button delete-post" onClick={() => {
            // ... delete post
            // then redirect, without page reload, by triggering a hidden Link
            document.querySelector('.trigger.go-home').click();
        }}>Delete Post</button>

        <Link to="/" className="trigger go-home hidden"></Link>

    </div>
);

Fondamentalement, une logique liée à une action (dans ce cas une post-suppression) finira par appeler un déclencheur pour la redirection. Ce n'est pas idéal car vous allez ajouter un "déclencheur" de nœud DOM à votre balisage afin de pouvoir facilement l'appeler en cas de besoin. De plus, vous interagirez directement avec le DOM, ce qui peut ne pas être souhaité dans un composant React.

Néanmoins, ce type de redirection n’est pas requis aussi souvent. Ainsi, un ou deux liens supplémentaires cachés dans le balisage de votre composant ne feraient pas beaucoup de mal, surtout si vous leur donnez des noms significatifs.

3
neatsu

La bonne réponse était pour moi au moment de l'écriture

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

Mais vous devez ajouter PropTypes à votre composant

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

N'oubliez pas d'importer des PropTypes

import PropTypes from 'prop-types';
3
webmaster

Pour React Router v4 +

En supposant que vous n’ayez pas besoin de naviguer pendant le rendu initial (pour lequel vous pouvez utiliser le composant <Redirect>], c’est ce que nous faisons dans notre application.

Définissez un itinéraire vide qui renvoie null, cela vous permettra d’obtenir l’accès à l’historique. Vous devez le faire au plus haut niveau où votre Router est défini.

Maintenant, vous pouvez faire tout ce qui peut être fait sur historique comme history.Push(), history.replace(), history.go(-1) etc!

import React from 'react';
import { HashRouter, Route } from 'react-router-dom';

let routeHistory = null;

export function navigateTo(path) {
  if(routeHistory !== null) {
    routeHistory.Push(path);
  }
}

export default function App(props) {
  return (
    <HashRouter hashType="noslash">
      <Route
        render={({ history }) => {
          routeHistory = history;
          return null;
        }}
      />
      {/* Rest of the App */}
    </HashRouter>
  );
}
1
Aftab Khan

Cela a fonctionné pour moi, aucune importation spéciale requise:

<input type="button" name="back" id="back" class="btn btn-primary" value="Back" onClick={() => { this.props.history.goBack() }} />

1
JJ_Coder4Hire