Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to listen to route changes in react router v4?

People also ask

How do I listen route changes in react router?

To detect route change with React Router, we can use the useLocation hook. import { useEffect } from "react"; import { useLocation } from "react-router-dom"; const SomeComponent = () => { const location = useLocation(); useEffect(() => { console. log("Location changed"); }, [location]); //... };

How do you navigate to a route reaction?

There are two ways to programmatically navigate with React Router - <Navigate /> and navigate() . You can get access to Navigate by importing it from the react-router-dom package and you can get access to navigate by using the custom useNavigate Hook.


I use withRouter to get the location prop. When the component is updated because of a new route, I check if the value changed:

@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>
  }
}

Hope it helps


To expand on the above, you will need to get at the history object. If you are using BrowserRouter, you can import withRouter and wrap your component with a higher-order component (HoC) in order to have access via props to the history object's properties and functions.

    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);

The only thing to be aware of is that withRouter and most other ways to access the history seem to pollute the props as they de-structure the object into it.

As others have said, this has been superseded by the hooks exposed by react router and it has a memory leak. If you are registering listeners in a functional component you should be doing so via useEffect and unregistering them in the return of that function.


v5.1 introduces the useful hook useLocation

https://reacttraining.com/blog/react-router-v5-1/#uselocation

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

function usePageViews() {
  let location = useLocation()

  useEffect(
    () => {
      ga.send(['pageview', location.pathname])
    },
    [location]
  )
}

function App() {
  usePageViews()
  return <Switch>{/* your routes here */}</Switch>
}

You should to use history v4 lib.

Example from there

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

withRouter, history.listen, and useEffect (React Hooks) works quite nicely together:

import React, { useEffect } from 'react'
import { withRouter } from 'react-router-dom'

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

    //...
}

export default withRouter(Component)

The listener callback will fire any time a route is changed, and the return for history.listen is a shutdown handler that plays nicely with useEffect.