Si vous ciblez des environnements de navigateur, vous devez utiliser le react-router-dom
package au lieu de react-router
. Ils suivent la même approche que React, afin de séparer le noyau, ( react
) et le code spécifique à la plate-forme, ( react-dom
, react-native
) avec la différence subtile que vous n'avez pas besoin d'installer deux packages distincts, de sorte que les packages d'environnement contiennent tout vous avez besoin. Vous pouvez l'ajouter à votre projet comme:
yarn add react-router-dom
ou
npm i react-router-dom
La première chose que vous devez faire est de fournir un <BrowserRouter>
composant le plus parent dans votre application. <BrowserRouter>
utilise l' history
API HTML5 et le gère pour vous, vous n'avez donc pas à vous soucier de l'instancier vous-même et de le transmettre au <BrowserRouter>
composant comme accessoire (comme vous le deviez dans les versions précédentes).
Dans la V4, pour naviguer par programmation, vous devez accéder à l' history
objet, qui est disponible via React context
, tant que vous avez un composant <BrowserRouter>
fournisseur en tant que parent le plus parent de votre application. La bibliothèque expose à travers le contexte l' router
objet, qui lui-même contient history
comme propriété. L' history
interface propose plusieurs méthodes de navigation, telles que push
, replace
et goBack
, entre autres. Vous pouvez consulter la liste complète des propriétés et méthodes ici .
Remarque importante pour les utilisateurs de Redux / Mobx
Si vous utilisez redux ou mobx comme bibliothèque de gestion d'état dans votre application, vous pouvez avoir rencontré des problèmes avec des composants qui devraient être sensibles à l'emplacement mais qui ne sont pas restitués après le déclenchement d'une mise à jour d'URL
Cela se produit car react-router
passe location
aux composants à l'aide du modèle de contexte.
La connexion et l'observateur créent des composants dont les méthodes shouldComponentUpdate font une comparaison superficielle de leurs accessoires actuels et de leurs prochains accessoires. Ces composants ne seront restitués que lorsqu'au moins un accessoire a changé. Cela signifie que pour garantir leur mise à jour lorsque l'emplacement change, ils devront recevoir un accessoire qui change lorsque l'emplacement change.
Les 2 approches pour résoudre ce problème sont:
- Enveloppez votre composant connecté dans un chemin sans chemin
<Route />
. L' location
objet actuel est l'un des accessoires qu'un <Route>
passe au composant qu'il rend
- Enveloppez votre composant connecté avec le
withRouter
composant d'ordre supérieur, qui a en fait le même effet et injecte location
qu'un accessoire
En mettant cela de côté, il existe quatre façons de naviguer par programme, ordonnées par recommandation:
1.- Utilisation d'un <Route>
composant
Il promeut un style déclaratif. Avant la v4, les
<Route />
composants étaient placés en haut de votre hiérarchie de composants, en pensant au préalable à la structure de vos itinéraires. Cependant, vous pouvez maintenant avoir des
<Route>
composants
n'importe où dans votre arborescence, ce qui vous permet d'avoir un contrôle plus fin pour le rendu conditionnel en fonction de l'URL.
Route
injecte
match
,
location
et
history
comme accessoires dans votre composant. Les méthodes de navigation ( par exemple
push
,
replace
,
goBack
...) sont disponibles en tant que propriétés de l'
history
objet.
Il y a 3 façons de rendre quelque chose avec un Route
, en utilisant soit component
, render
soit des children
accessoires, mais n'en utilisez pas plus d'un en même temps Route
. Le choix dépend du cas d'utilisation, mais fondamentalement, les deux premières options ne rendront votre composant que s'il path
correspond à l'emplacement de l'URL, tandis qu'avec children
le composant sera rendu si le chemin correspond à l'emplacement ou non (utile pour ajuster l'interface utilisateur en fonction de l'URL correspondant à).
Si vous souhaitez personnaliser votre composant de rendu de sortie , vous devez envelopper votre composant dans une fonction et utilisez l' render
option pour passer à votre composant les autres accessoires que vous désirez, à part 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.- Utiliser withRouter
HoC
Ce composant d'ordre supérieur injectera les mêmes accessoires que Route
. Cependant, il comporte la limitation selon laquelle vous ne pouvez avoir qu'une seule 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.- Utiliser un Redirect
composant
Le rendu a
<Redirect>
permet d'accéder à un nouvel emplacement. Mais gardez à l'esprit que,
par défaut , l'emplacement actuel est remplacé par le nouveau, comme les redirections côté serveur (HTTP 3xx). Le nouvel emplacement est fourni par
to
prop, qui peut être une chaîne (URL vers laquelle rediriger) ou un
location
objet. Si vous souhaitez plutôt
insérer une nouvelle entrée dans l'historique , passez également un
push
accessoire et définissez-le sur
true
<Redirect to="/your-new-location" push />
4.- Accès router
manuel via le contexte
Un peu découragé car le
contexte est toujours une API expérimentale et il est susceptible de se casser / changer dans les futures versions de React
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 existe également d'autres composants de routeur destinés à des écosystèmes autres que des navigateurs, tels que ceux <NativeRouter>
qui reproduisent une pile de navigation en mémoire et ciblent la plate-forme React Native, disponibles via le react-router-native
package.
Pour toute référence supplémentaire, n'hésitez pas à consulter les documents officiels . Il y a aussi une vidéo réalisée par l'un des co-auteurs de la bibliothèque qui fournit une introduction assez cool à react-router v4, mettant en évidence certains des changements majeurs.