web-dev-qa-db-fra.com

Comment écouter les changements de route dans le routeur réagissent v4?

J'ai quelques boutons qui servent de routes. À chaque changement d'itinéraire, je veux m'assurer que le bouton actif est modifié.

Existe-t-il un moyen d'écouter les changements de route dans le routeur réagit v4?

63
Kasper

J'utilise withRouter pour obtenir le location prop. Lorsque le composant est mis à jour à cause d'un nouvel itinéraire, je vérifie si la valeur a changé:

@withRouter
class App extends React.Component {

  static propTypes = {
    location: React.PropTypes.object.isRequired
  }

  // ...

  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      this.onRouteChanged();
    }
  }

  onRouteChanged() {
    console.log("ROUTE CHANGED");
  }

  // ...
  render(){
    return <Switch>
        <Route path="/" exact component={HomePage} />
        <Route path="/checkout" component={CheckoutPage} />
        <Route path="/success" component={SuccessPage} />
        // ...
        <Route component={NotFound} />
      </Switch>
  }
}

J'espère que ça aide

96
ledfusion

Pour développer ce qui précède, vous aurez besoin d’obtenir l’objet historique. Si vous utilisez BrowserRouter, vous pouvez importer withRouter et envelopper votre composant avec un composant d'ordre supérieur (HoC) afin d'avoir accès via des accessoires aux propriétés et fonctions de l'objet historique.

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

const myComponent = ({ history }) => {

    history.listen((location, action) => {
        // location is an object like window.location
        console.log(action, location.pathname, location.state)
    });

    return <div>...</div>;
};

export default withRouter(myComponent);

La seule chose dont il faut être conscient, c’est que withRouter et la plupart des autres moyens d’accéder à la variable history semblent polluer les accessoires lorsqu’ils y décomposent l’objet.

38
Sam Parmenter

Vous devriez utiliser history v4 lib.

Exemple de

history.listen((location, action) => {
  console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`)
  console.log(`The last navigation action was ${action}`)
})
17
Sergey Reutskiy

Avec crochets:

import { useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { history as historyShape } from 'react-router-prop-types'

const DebugHistory = ({ history }) => {
  useEffect(() => {
    console.log('> Router', history.action, history.location])
  }, [history.location.key])

  return null
}

DebugHistory.propTypes = { history: historyShape }

export default withRouter(DebugHistory)

Importation et rendu en tant que composant <DebugHistory>

2
Tymek

withRouter, history.listen et useEffect (React Hooks) fonctionne assez bien ensemble:

const Component = ({ history }) => {
    useEffect(() => history.listen(() => {
        // do something on route change
        // for my example, close a drawer
    }), [])

    //...
}

export default withRouter(Component)

Le rappel de l'auditeur se déclenche chaque fois qu'un itinéraire est modifié et le retour de history.listen est un gestionnaire d'arrêt qui fonctionne bien avec useEffect.

2
Alex

Dans certains cas, vous pouvez utiliser l'attribut render au lieu de component, de cette façon:

class App extends React.Component {

    constructor (props) {
        super(props);
    }

    onRouteChange (pageId) {
        console.log(pageId);
    }

    render () {
        return  <Switch>
                    <Route path="/" exact render={(props) => { 
                        this.onRouteChange('home');
                        return <HomePage {...props} />;
                    }} />
                    <Route path="/checkout" exact render={(props) => { 
                        this.onRouteChange('checkout');
                        return <CheckoutPage {...props} />;
                    }} />
                </Switch>
    }
}

Notez que si vous modifiez l’état dans la méthode onRouteChange, cela pourrait entraîner l’erreur «Profondeur de mise à jour maximale dépassée».

0
Fernando