Je viens de remplacer la react-router
v3 en v4.
Mais je ne sais pas comment naviguer par programmation dans la fonction membre de a Component
. c'est-à-dire dans la handleClick()
fonction que je veux naviguer après /path/some/where
avoir traité certaines données. Je le faisais par:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
Mais je ne trouve pas de telles interfaces dans la v4.
Comment naviguer avec v4?
reactjs
ecmascript-6
react-router-v4
Colin Witkamp
la source
la source
Component
? Par exemple, à l'intérieur des actions redux.Réponses:
Si vous ciblez des environnements de navigateur, vous devez utiliser le
react-router-dom
package au lieu dereact-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 Reactcontext
, 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 contienthistory
comme propriété. L'history
interface propose plusieurs méthodes de navigation, telles quepush
,replace
etgoBack
, 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'URLCela se produit car
react-router
passelocation
aux composants à l'aide du modèle de contexte.Les 2 approches pour résoudre ce problème sont:
<Route />
. L'location
objet actuel est l'un des accessoires qu'un<Route>
passe au composant qu'il rendwithRouter
composant d'ordre supérieur, qui a en fait le même effet et injectelocation
qu'un accessoireEn mettant cela de côté, il existe quatre façons de naviguer par programme, ordonnées par recommandation:
1.- Utilisation d'un
Il promeut un style déclaratif. Avant la v4, les<Route>
composant<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
injectematch
,location
ethistory
comme accessoires dans votre composant. Les méthodes de navigation ( par exemplepush
,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 soitcomponent
,render
soit deschildren
accessoires, mais n'en utilisez pas plus d'un en même tempsRoute
. Le choix dépend du cas d'utilisation, mais fondamentalement, les deux premières options ne rendront votre composant que s'ilpath
correspond à l'emplacement de l'URL, tandis qu'avecchildren
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, à partmatch
,location
ethistory
. Un exemple pour illustrer:2.- Utiliser
withRouter
HoCCe 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.3.- Utiliser un
Le rendu aRedirect
composant<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 parto
prop, qui peut être une chaîne (URL vers laquelle rediriger) ou unlocation
objet. Si vous souhaitez plutôt insérer une nouvelle entrée dans l'historique , passez également unpush
accessoire et définissez-le surtrue
4.- Accès
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 Reactrouter
manuel via le contexteInutile 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 lereact-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.
la source
withRouter
dereact-router-dom
withRouter
dereact-router-dom
. Le history.push change l'url, mais il ne semble pas le charger<Route>
jusqu'à ce que je force à rafraîchir la page ...<Router>
intérieur un composant React qui est décoré@observer
, ce qui déclenche ce problème . Le travail consiste à disposer@withRouter
de chacun de ces composants React.withRouter
c'est tout simplement un HOC qui utilise unRoute
sous le capot. Ce qui signifie qu'il n'utilise que 3 accessoires, historique, correspondance et emplacement . Dans l'exemple ci-dessus, il semble que cepush
soit un accessoire quiwithRouter
viendrait s'ajouterButtonToNavigate
, mais ce n'est pas le cas.props.history.push
devrait être utilisé à la place. J'espère que cela aide ceux qui étaient un peu confus.browserHistory.push('/path/some/where')
semble juste beaucoup plus simple. Les auteurs tentent de décourager la programmation impérative, mais parfois cela fonctionne mieux!La façon la plus simple de le faire:
this.props.history.push("/new/url")
Remarque:
history
prop
composant parent parent au composant auquel vous souhaitez appeler l'action s'il n'est pas disponible.la source
this.props.history
dans votre composant, vous pouvezimport {withRouter} from 'react-router-dom'
et puisexport default withRouter(MyComponent)
(ouconst MyComponent = withRouter(...)
) et il insérera l'history
élément dans les accessoires de votre composant.history.push
et simplement déclencher la mise à jour comme lorsque nous cliquons sur<Link>
J'ai eu un problème similaire lors de la migration vers React-Router v4, je vais donc essayer d'expliquer ma solution ci-dessous.
Veuillez ne pas considérer cette réponse comme la bonne façon de résoudre le problème, j'imagine qu'il y a de bonnes chances que quelque chose de mieux se produise lorsque React Router v4 devient plus mature et quitte la version bêta (il peut même déjà exister et je ne l'ai tout simplement pas découvert) .
Pour le contexte, j'ai eu ce problème parce que j'utilise occasionnellement
Redux-Saga
pour modifier par programme l'objet historique (par exemple, lorsqu'un utilisateur réussit à s'authentifier).Dans les documents React Router, jetez un œil au
<Router>
composant et vous pouvez voir que vous avez la possibilité de passer votre propre objet historique via un accessoire. C'est l'essence de la solution - nous fournissons l'objet historique àReact-Router
partir d'un module global .Pas:
yarn add history
ounpm install history --save
créer un fichier appelé
history.js
dans votreApp.js
dossier level (c'était ma préférence)Ajoutez cet objet d'historique à votre composant de routeur comme ceci
Ajustez l'URL comme avant en important votre objet d'historique global:
Tout devrait rester synchronisé maintenant, et vous avez également accès à un moyen de définir l'objet historique par programme et non via un composant / conteneur.
la source
Route
composant.TL; DR:
La réponse simple et déclarative est que vous devez utiliser
<Redirect to={URL} push={boolean} />
en combinaison avecsetState()
Exemple complet ici . Lisez plus ici .
PS. L'exemple utilise ES7 + Property Initializers pour initialiser l'état. Regardez ici aussi, si vous êtes intéressé.
la source
history.push()
méthodes.Utilisation
useHistory
crochet si vous utilisez des composants de fonctionVous pouvez utiliser le
useHistory
hook pour obtenir unehistory
instance.le
useHistory
hook vous donne accès à l'instance d'historique que vous pouvez utiliser pour naviguer.Utilisation
history
propriété à l'intérieur des composants de la pageReact Router injecte certaines propriétés, y compris les
history
composants de page.Enveloppez les composants enfants
withRouter
pour injecter les propriétés du routeurwithRouter
le wrapper injecte les propriétés du routeur aux composants. Par exemple, vous pouvez utiliser ce wrapper pour injecter un composant de bouton de déconnexion du routeur placé dans le menu utilisateur.la source
Vous pouvez également simplement utiliser des accessoires pour accéder à l'objet historique:
this.props.history.push('new_url')
la source
this.props.history
dans votre composant, vous pouvezimport {withRouter} from 'react-router-dom'
et puisexport default withRouter(MyComponent)
(ouconst MyComponent = withRouter(...)
) et il insérera l'history
élément dans les accessoires de votre composant.Étape 1: Il n'y a qu'une seule chose à importer par dessus:
Étape 2: Dans votre itinéraire, passez l'historique:
Étape 3: l'historique est accepté comme partie des accessoires dans le prochain composant, vous pouvez donc simplement:
C'était facile et vraiment puissant.
la source
Cela marche:
la source
Ma réponse est similaire à celle d' Alex . Je ne sais pas pourquoi React-Router a rendu cela si compliqué inutilement. Pourquoi devrais-je avoir à envelopper mon composant avec un HoC juste pour avoir accès à ce qui est essentiellement un global?
Quoi qu'il en soit, si vous regardez comment ils ont été mis en œuvre
<BrowserRouter>
, ce n'est qu'un petit tour d'horizon de l' histoire .Nous pouvons extraire cet historique pour pouvoir l'importer de n'importe où. L'astuce, cependant, est que si vous effectuez un rendu côté serveur et que vous essayez
import
le module d'historique, cela ne fonctionnera pas car il utilise des API uniquement pour le navigateur. Mais c'est OK car nous ne redirigeons généralement qu'en réponse à un clic ou à un autre événement côté client. Il est donc probablement OK de le simuler:Avec l'aide de webpack, nous pouvons définir quelques vars afin que nous sachions dans quel environnement nous sommes:
Et maintenant vous pouvez
De partout. Cela ne fera que renvoyer un module vide sur le serveur.
Si vous ne voulez pas utiliser ces vars magiques, vous n'aurez qu'à le faire
require
dans l'objet global où il est nécessaire (à l'intérieur de votre gestionnaire d'événements).import
ne fonctionnera pas car il ne fonctionne qu'au niveau supérieur.la source
Je pense que @rgommezz couvre la plupart des cas moins celui que je pense que c'est assez important.
Cela me permet d'écrire un service simple avec des actions / appels que je peux appeler pour faire la navigation depuis n'importe quel composant que je veux sans faire beaucoup de HoC sur mes composants ...
On ne sait pas pourquoi personne n'a fourni cette solution auparavant. J'espère que cela aide, et si vous voyez un problème avec lui, faites le moi savoir.
la source
Je teste la v4 depuis quelques jours maintenant et .. je l'adore jusqu'à présent! Cela prend tout son sens après un certain temps.
J'ai également eu la même question et j'ai trouvé que la gérer comme celle-ci fonctionnait le mieux (et pourrait même être la façon dont elle est prévue). Il utilise l'état, un opérateur ternaire et
<Redirect>
.Dans le constructeur ()
Dans le rendu ()
Dans le gestionnaire de clics ()
J'espère que ça aide. Faites le moi savoir.
la source
Je me suis débattu avec cela pendant un certain temps - quelque chose de si simple, mais si compliqué, parce que ReactJS est juste une façon complètement différente d'écrire des applications Web, c'est très étranger pour nous, les personnes âgées!
J'ai créé un composant séparé pour faire abstraction du gâchis:
Ajoutez-le ensuite à votre
render()
méthode:la source
Puisqu'il n'y a pas d'autre moyen de faire face à cette conception horrible, j'ai écrit un composant générique qui utilise l' approche
withRouter
HOC . L'exemple ci-dessousbutton
encapsule un élément, mais vous pouvez passer à n'importe quel élément cliquable dont vous avez besoin:Usage:
la source
Si vous n'avez pas trouvé this.props.history disponible dans votre composant, essayez ceci
la source
Comme parfois je préfère changer de route par application puis par boutons, c'est un exemple de travail minimal qui fonctionne pour moi:
la source
Pour ceux d'entre vous qui ont besoin de rediriger avant d'initialiser complètement un routeur à l'aide de
React Router
ouReact Router Dom
Vous pouvez fournir une redirection en accédant simplement à l'objet historique et en poussant un nouvel état dessus dans votre construction deapp.js
. Considérer ce qui suit:Ici, nous voulons changer les routes de sortie dépendant d'un sous-domaine, en interagissant avec l'objet historique avant que le composant ne soit rendu, nous pouvons effectivement rediriger tout en laissant nos routes intactes.
la source