React Router v4 - Comment obtenir la route actuelle?

181

Je voudrais afficher un titledans<AppBar /> qui est en quelque sorte passé de l'itinéraire actuel.

Dans React Router v4, comment pourrait- <AppBar />on faire passer la route actuelle dans son titleaccessoire?

  <Router basename='/app'>
    <main>
      <Menu active={menu} close={this.closeMenu} />
      <Overlay active={menu} onClick={this.closeMenu} />
      <AppBar handleMenuIcon={this.handleMenuIcon} title='Test' />
      <Route path='/customers' component={Customers} />
    </main>
  </Router>

Y at - il un moyen de passer un titre personnalisé d'une coutume propsur <Route />?

Raphael Rafatpanah
la source

Réponses:

76

Dans la version 5.1 de react-router, il existe un hook appelé useLocation , qui renvoie l'objet de localisation actuel. Cela peut être utile chaque fois que vous avez besoin de connaître l'URL actuelle.

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

function HeaderView() {
  let location = useLocation();
  console.log(location.pathname);
  return <span>Path : {location.pathname}</span>
}

vr12
la source
7
Veuillez noter que cela ne peut être utilisé qu'à l'intérieur du DOM du routeur (c'est-à-dire des composants chid, pas dans la classe / composant fonctionnel où le routeur est utilisé). Cela peut être évident mais pas pour un débutant comme moi :-) J'obtenais tout le temps l'erreur "useContext is undefined"
BennyHilarious
cela ne fonctionnera pas non plus si un routeur a redirectété utilisé. cela lira le chemin avant la redirection
Sonic Soul
merci pour cette réponse ...
bellabelle
212

Dans React Router 4, la route actuelle est en - this.props.location.pathname. Obtenez this.propset vérifiez. Si vous ne voyez toujours pas, location.pathnamevous devez utiliser le décorateurwithRouter .

Cela pourrait ressembler à ceci:

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

const SomeComponent = withRouter(props => <MyComponent {...props}/>);

class MyComponent extends React.Component {
  SomeMethod () {
    const {pathname} = this.props.location;
  }
}
Con Posidielov
la source
14
veuillez noter que ce n'est pas toujours vrai: avec react-router4, si votre composant est rendu à un niveau supérieur par rapport à certaines routes imbriquées (qui étend le chemin plus tard), l'emplacement.pathname à l'intérieur de WithRouter sera différent dewindow.location.pathname
maioman
3
Comment l'obtenir par programme en dehors d'un composant React?
trusktr
78

Si vous utilisez des modèles, réagissent pour où la fin de votre fichier ressemble réagit comme ceci: export default SomeComponentvous devez utiliser le composant d'ordre supérieur (souvent désigné comme un « hoc »), withRouter.

Tout d'abord, vous devrez importer withRoutercomme suit:

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

Ensuite, vous voudrez utiliser withRouter . Vous pouvez le faire en modifiant l'exportation de votre composant. Il est probable que vous souhaitiez passer de export default ComponentNameà export default withRouter(ComponentName).

Ensuite, vous pouvez obtenir l'itinéraire (et d'autres informations) à partir des accessoires. Plus précisément, location, matchet history. Le code pour cracher le chemin serait:

console.log(this.props.location.pathname);

Un bon article avec des informations supplémentaires est disponible ici: https://reacttraining.com/react-router/core/guides/philosophy

lowcrawler
la source
Mais comment obtenir l'URL complète?
Tessaracter
18

Voici une solution utilisant history Lire la suite

import { createBrowserHistory } from "history";

const history = createBrowserHistory()

à l'intérieur du routeur

<Router>
   {history.location.pathname}
</Router>
Wael Mohamed BETTAYEB
la source
3
Pour ceux d'entre nous sur le chemin fonctionnel de réaction, cette réponse est la plus logique. Ce this.props....n'est que du bruit à nos oreilles.
KhoPhi
17

Il y a un hook appelé useLocation dans react -router v5, pas besoin de HOC ou d'autres choses, c'est très succinct et pratique.

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

const ExampleComponent: React.FC = () => {
  const location = useLocation();  

  return (
    <Router basename='/app'>
      <main>
        <AppBar handleMenuIcon={this.handleMenuIcon} title={location.pathname} />
      </main>
    </Router>
  );
}
Alexandre Kim
la source
Cette réponse devrait être notée beaucoup plus haut. Utiliser le hook est tellement plus facile et intuitif que ces autres solutions (si sur RR v5)
BrDaHa
10

Je pense que l'auteur de React Router (v4) vient d'ajouter cela withRouter HOC pour apaiser certains utilisateurs. Cependant, je pense que la meilleure approche consiste simplement à utiliser un accessoire de rendu et à créer un simple composant PropsRoute qui transmet ces accessoires. Ceci est plus facile à tester car il ne "connecte" pas le composant comme le fait withRouter. Ayez un tas de composants imbriqués enveloppés dans withRouter et ce ne sera pas amusant. Un autre avantage est que vous pouvez également utiliser ce passage à travers les accessoires que vous souhaitez pour la Route. Voici l'exemple simple d'utilisation de render prop. (à peu près l'exemple exact de leur site Web https://reacttraining.com/react-router/web/api/Route/render-func ) (src / components / routes / props-route)

import React from 'react';
import { Route } from 'react-router';

export const PropsRoute = ({ component: Component, ...props }) => (
  <Route
    { ...props }
    render={ renderProps => (<Component { ...renderProps } { ...props } />) }
  />
);

export default PropsRoute;

utilisation: (remarquez pour obtenir les paramètres d'itinéraire (match.params), vous pouvez simplement utiliser ce composant et ceux-ci vous seront transmis)

import React from 'react';
import PropsRoute from 'src/components/routes/props-route';

export const someComponent = props => (<PropsRoute component={ Profile } />);

notez également que vous pouvez également passer les accessoires supplémentaires que vous voulez de cette façon

<PropsRoute isFetching={ isFetchingProfile } title="User Profile" component={ Profile } />
hal9000
la source
3
Est-il possible de transformer cette solution en un codepen? Je veux utiliser la solution la plus correcte mais je ne comprends vraiment pas comment la mettre en œuvre.
LAdams87
7

A dit Con Posidielov , l'itinéraire actuel est présent this.props.location.pathname.

Mais si vous voulez faire correspondre un champ plus spécifique comme une clé (ou un nom), vous pouvez utiliser matchPath pour trouver la référence d'itinéraire d'origine.

import { matchPath } from `react-router`

const routes = [{
  key: 'page1'
  exact: true,
  path: '/page1/:someparam/',
  component: Page1,
},
{
  exact: true,
  key: 'page2',
  path: '/page2',
  component: Page2,
},
]

const currentRoute = routes.find(
  route => matchPath(this.props.location.pathname, route)
)

console.log(`My current route key is : ${currentRoute.key}`)
Rasta_boy
la source
0

Ajouter

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

Puis changez votre exportation de composants

export default withRouter(ComponentName)

Ensuite, vous pouvez accéder à l'itinéraire directement dans le composant lui-même (sans rien toucher d'autre dans votre projet) en utilisant:

window.location.pathname

Testé en mars 2020 avec: "version": "5.1.2"

Siobhan
la source
Pas sûr de celui-ci. Bien sûr, cela donne le chemin d'accès actuel, mais cela ne change pas si je navigue vers une nouvelle page.
alex le