387 votes

Naviguer par programme en utilisant react router V4

Je viens de remplacer react-router de v3 à v4.
Mais je ne suis pas sûr de savoir comment naviguer par programme dans la fonction membre d’un Component . c'est-à-dire dans la fonction handleClick() je souhaite accéder à /path/some/where après le traitement de certaines données. Je faisais ça par:

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

Mais je ne trouve pas de telles interfaces dans la v4.
Comment puis-je naviguer en utilisant v4?

452voto

rgommezz Points 6193

Si vous utilisez le navigateur environnements, vous devez utiliser react-router-dom plutôt react-router. Ils suivent la même approche que fait Réagir, afin de le séparer de la base, (react) et la plate-forme de code spécifique (react-dom, react-native ) avec la subtile différence que vous n'avez pas besoin d'installer deux paquets séparés, de sorte que l'environnement paquets contiennent tout ce dont vous avez besoin. Vous pouvez l'ajouter à votre projet:

yarn add react-router-dom

ou

npm i react-router-dom

La première chose que vous devez faire est de fournir un <BrowserRouter> comme le plus haut parent composant dans votre application. <BrowserRouter> utilise le HTML5 history API et gère pour vous, si vous n'avez pas à vous soucier de l'instanciation de vous-même et en passant vers le bas à l' <BrowserRouter> composant comme un accessoire (comme vous devait faire dans les versions précédentes).

En V4, pour la navigation par programmation, vous devez accéder à l' history de l'objet, qui est disponible par le biais de Réagir context, aussi longtemps que vous avez un <BrowserRouter> fournisseur de composant dans le haut de la plupart des parents dans votre application. La bibliothèque expose le contexte de l' router objet, qui contient lui-même history comme une propriété. L' history interface offre plusieurs méthodes de navigation, telles que l' push, replace et goBack,, entre autres. Vous pouvez consulter toute la liste des propriétés et méthodes ici.

Remarque importante pour Redux/Mobx utilisateurs

Si vous utilisez redux ou mobx que votre état de gestion de bibliothèque dans votre application, vous pouvez avoir rencontré des problèmes avec les composants qui doivent être géolocalisées, mais ne sont pas ré-rendu après le déclenchement de l'URL de mise à jour

Que se passe parce qu' react-router passes location de composants en utilisant le modèle de contexte.

Les deux se connecter et observateur créer des composants dont shouldComponentUpdate méthodes de faire un peu de la comparaison de leurs accessoires et de leurs côté des accessoires. Ces composants ne re-rendre lorsqu'au moins une hélice a changé. Cela signifie que, pour assurer leur mise à jour lors de la modification d'emplacement, ils doivent être donné un accessoire qui change lorsque les modifications de l'emplacement.

Les 2 approches pour la résolution de ce problème sont:

  • Enveloppez vos connecté composant dans un pathless <Route />. Le courant location objet est l'un des accessoires que l' <Route> de passes pour le composant, il rend
  • Enveloppez votre connecté avec volet de l' withRouter -supérieur composante de l'ordre, qui en fait a le même effet et injecte location comme un accessoire

Paramètre de côté, il y a quatre façons de naviguer par programmation, commandé par la recommandation:

1.- À l'aide d'un <Route> de la Composante

Il fait la promotion d'un style déclaratif. Avant la v4, <Route /> des composants ont été placés en haut de votre hiérarchie des composants, avoir à penser à vos itinéraires structure à l'avance. Cependant, maintenant vous pouvez avoir <Route> des composants de n'importe où dans votre arbre, vous permettant d'avoir un contrôle plus fin pour conditionnellement rendu en fonction de l'URL. Route injecte match, location et history accessoires dans votre composant. Les méthodes de navigation (comme push, replace, goBack...) sont disponibles en tant que propriétés de l' history objet.

Il existe 3 façons de rendre quelque chose avec un Route, soit à l'aide d' component, render ou children d'accessoires, mais ne pas utiliser plus d'un dans le même Route. Le choix dépend du cas d'utilisation, mais, fondamentalement, les deux premières options ne rendre votre composant si l' path correspond à l'emplacement de l'url, alors qu'avec children le composant sera rendu si le chemin d'accès correspond à l'emplacement ou pas (utile pour le réglage de l'INTERFACE utilisateur basé sur l'URL correspondante).

Si vous voulez personnaliser votre composant le rendu de la sortie, vous avez besoin d'envelopper votre composant dans une fonction et l'utilisation de l' render option, afin de passer à votre composant de tous les autres accessoires que vous désirez, en dehors de match, location et history. Un exemple pour illustrer:

import { BrowserRouter as Router } from 'react-router-dom'

const ButtonToNavigate = ({ title, history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    {title}
  </button>
);

const SomeComponent = () => (
  <Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)    

const App = () => (
  <Router>
    <SomeComponent /> // Notice how in v4 we can have any other component interleaved
    <AnotherComponent />
  </Router>
);

2.- À L'Aide De withRouter - HoC

Cet accroissement de la composante de l'ordre va injecter la même béquilles, Route. Cependant, il porte le long de la limite que vous pouvez avoir seulement 1 ad HoC par fichier.

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

const ButtonToNavigate = ({ history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    Navigate
  </button>
);


ButtonToNavigate.propTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired,
  }),
};

export default withRouter(ButtonToNavigate);

3.- À l'aide d'un Redirect de la composante

Rendu un <Redirect> de naviguer vers un nouvel emplacement. Mais gardez à l'esprit que, par défaut, l'emplacement actuel est remplacé par le nouveau, comme le serveur de redirection HTTP (3xx). Le nouvel emplacement est fourni par to prop, qui peut être une chaîne de caractères (URL de redirection) ou un location objet. Si vous voulez pousser une nouvelle entrée dans l'histoire au lieu de cela, passer un push prop ainsi et réglez - true

<Redirect to="/your-new-location" push />

4.- Accéder router manuellement par l'intermédiaire de contexte

Un peu découragé parce que le contexte est encore au stade expérimental de l'API et il est susceptible de pause/changer dans les futures versions de Réagir

const ButtonToNavigate = (props, context) => (
  <button
    type="button"
    onClick={() => context.router.history.push('/my-new-location')}
  >
    Navigate to a new location
  </button>
);

ButtonToNavigate.contextTypes = {
  router: React.PropTypes.shape({
    history: React.PropTypes.object.isRequired,
  }),
};

Inutile de dire qu'il y a aussi d'autres Routeur composants qui sont destinés à être pour les non navigateur écosystèmes, tels que l' <NativeRouter> qui réplique une pile de navigation dans la mémoire et les cibles de Réagir plate-forme Native, disponible par le biais react-router-native package.

Pour toute autre référence, n'hésitez pas à jeter un coup d'oeil à l' officiel docs. Il y a aussi une vidéo faite par l'un des co-auteurs de la bibliothèque qui fournit un assez cool introduction à réagir-routeur v4, mettant en évidence certains des principaux changements.

169voto

Jikku Jose Points 399

Le moyen le plus simple de le faire:

this.props.history.push("/new/url")

Remarque:

  • Vous souhaiterez peut-être transmettre le history prop du composant parent au composant sur lequel vous souhaitez appeler l'action si elle n'est pas disponible.

58voto

Alex Mann Points 627

J'ai eu un problème similaire lors de la migration de plus de Réagir-Routeur v4 donc je vais essayer d'expliquer ma solution ci-dessous.

S'il vous plaît ne considérez pas que cette réponse est la bonne façon de résoudre le problème, j'imagine qu'il y a une bonne chance de quelque chose de mieux surviennent Réagir Routeur v4 devient de plus en plus matures et les feuilles bêta (Il peut même exister déjà et je n'ai même pas le découvrir).

Pour le contexte, j'ai eu ce problème parce que j'utilise occasionnellement Redux-Saga de programmation pour changer l'histoire de l'objet (dire lorsqu'un utilisateur s'authentifie avec succès).

Dans le Réagir Routeur docs, prendre un coup d'oeil à l' <Router> de la composante et vous pouvez le voir, vous avez la possibilité de passer votre propre histoire de l'objet par l'intermédiaire d'un prop. C'est l'essence même de la solution - nous offre l'histoire de l'objet à l' React-Router d'un mondial du module.

Étapes:

  1. Installer l'histoire mnp module - yarn add history ou npm install history --save
  2. créez un fichier appelé history.js votre App.js dossier de niveau (c'est ma préférence)

    // src/history.js
    
    import createHistory from 'history/createBrowserHistory';
    export default createHistory();`
    
  3. Ajouter cette histoire d'objet à votre Routeur composant comme

    // src/App.js
    
    import history from '../your/path/to/history.js;'
    <Router history={history}>
    // Route tags here
    </Router>
    
  4. Ajuster l'URL juste comme avant, par l'importation de votre histoire mondiale de l'objet:

    import history from '../your/path/to/history.js;'
    history.push('new/path/here/');
    

Tout devrait rester synchronisés jusqu'à maintenant, et vous avez également accès à un moyen de réglage de l'histoire de l'objet par programme et non par l'intermédiaire d'un composant/conteneur.

49voto

Lyubomir Points 10274

TL;DR:

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

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

push: boolean - si la valeur est true, la redirection de pousser une nouvelle entrée dans l'histoire au lieu de remplacer l'actuel.


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 plus ici.

PS. L'exemple utilise ES7+ Propriété des Initialiseurs de l'initialisation de l'état. Regardez ici ainsi, si vous êtes intéressé.

11voto

user1445685 Points 33

peut aussi simplement utiliser des accessoires: this.props.history.push('new_url')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X