Comment gérer la navigation programmatique avec react-router ?

La bibliothèque Javascript React est pensée pour vous aider à concevoir des applications monopage, comme l'est par exemple Facebook (les créateurs de React). Vous naviguez sur une seule page qui évolue selon vos actions. Il n'y a donc en principe pas de redirection vers une autre URL. Il est quand même possible de naviguer vers une autre URL grâce à un composant de la librairie. Il existe ensuite différentes méthodes pour implémenter la redirection.

Pour pouvoir changer l'URL dans une application développée avec React, vous avez besoin d'un composant supplémentaire nommé "react-router-dom". Il vous permettra d'interagir avec le routeur de React pour modifier l'URL de la page courante, et donc effectuer une redirection. Il est possible d'installer ce paquet avec l'un des deux gestionnaires de paquets liés à NodeJS : Yarn ou NPM.

yarn add react-router-dom
npm i react-router-dom

Dans le composant le plus élevé de votre application, vous devez inclure le composant "BrowserRouter". Ce dernier vous permettra d'utiliser l'API "History" de HTML5 afin de manipuler l'historique du navigateur et ainsi changer les URL de navigation sans changer de page.

La première solution pour effectuer une redirection est l'utilisation d'une balise <route>. Cette balise contiendra le bouton de navigation. Celui-ci permettra lors du clic de changer l'URL en cours de la page. Il est nécessaire d'utiliser une fonction de rendu pour afficher le bouton. Cela vous permet de modifier l'affichage de la façon dont vous le souhaitez. Vous pouvez utiliser cette méthode n'importe où dans votre application.

import { BrowserRouter as Router } from 'react-router-dom'
const BoutonDeNavigation = ({ libelle, history }) => (
  <button type="button" onClick={() => history.push('/ma-nouvelle-url')}>{libelle}</button>
);
const SomeComponent = () => (
  <Route path="/" render={(props) => <BoutonDeNavigation {...props} title="Changer de page" />} />
)
const App = () => (
  <Router>
    <SomeComponent />
    <AnotherComponent />
  </Router>
);

Vous pouvez faire également appel au HOC (High Order Component) "withRouter". Il simplifie l'écriture du code pour effectuer la redirection. Vous êtes par contre limité à un seul HOC par fichier, c'est donc à vous de déterminer si vous pouvez l'utiliser.

import { withRouter } from 'react-router-dom'
const BoutonDeNavigation = ({ history }) => (
  <button type="button" onClick={() => history.push('/ma-nouvelle-url')}>Changer de page</button>
);
BoutonDeNavigation.propTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired,
  }),
};
export default withRouter(BoutonDeNavigation);

La librairie React fournit un composant permettant d'effectuer directement une redirection. Il s'agit du composant "<redirect>". Par défaut, afficher ce composant redirige comme le fait une redirection HTTP classique avec un chargement de la page. Il existe cependant un attribut nommé "push". Si vous fixez sa valeur à "true", l'URL est envoyée à l'historique du navigateur sans redirection HTTP.

<Redirect to="/ma-nouvelle-url" push />

La dernière solution consiste à utiliser l'API Context. La méthode "context.history.push()" permet d'envoyer une nouvelle URL dans l'historique du navigateur. Vous devez cependant faire attention avec cette méthode car l'API Context est considérée comme expérimentale. Son fonctionnement peut évoluer, ce qui peut causer des problèmes de fonctionnement pour votre application avec une future version de React.

const BoutonDeNavigation = (props, context) => (
  <button type="button" onClick={() => context.router.history.push('/ma-nouvelle-url')}>Changer de page</button>
);
BoutonDeNavigation.contextTypes = {
  router: React.PropTypes.shape({
    history: React.PropTypes.object.isRequired
  })
};

JavaScript