Anurag Jain
Anurag Jain

Reputation: 453

React router v4 route onchange event

Is there any way to fire an event when route changes with react router v4. I need to fire a function on every route change. I use BrowserRouter and Switch from react-router-dom on client side in universal react-redux application.

Upvotes: 4

Views: 13841

Answers (2)

Ukr
Ukr

Reputation: 2704

React: v15.x, React Router: v4.x

components/core/App.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { BrowserRouter } from 'react-router-dom';


class LocationListener extends Component {
  static contextTypes = {
    router: PropTypes.object
  };

  componentDidMount() {
    this.handleLocationChange(this.context.router.history.location);
    this.unlisten = 
this.context.router.history.listen(this.handleLocationChange);
  }

  componentWillUnmount() {
    this.unlisten();
  }

  handleLocationChange(location) {
    // your staff here
    console.log(`- - - location: '${location.pathname}'`);
  }

  render() {
    return this.props.children;
  }
}    

export class App extends Component {
  ...

  render() {
    return (
      <BrowserRouter>
        <LocationListener>
         ...
        </LocationListener>
      </BrowserRouter>
    );
  }
}

index.js:

import App from 'components/core/App';

render(<App />, document.querySelector('#root'));

Upvotes: 5

Dennis
Dennis

Reputation: 714

I resolved this by wrapping my application with an additional component. That component is used in a Route so it also has access to the history prop.

<BrowserRouter>
  <Route component={App} />
</BrowserRouter>

The App component subscribes on history changes, so I can do something whenever the route changes:

export class App extends React.Component {
  componentWillMount() {
    const { history } = this.props;
    this.unsubscribeFromHistory = history.listen(this.handleLocationChange);
    this.handleLocationChange(history.location);
  }

  componentWillUnmount() {
    if (this.unsubscribeFromHistory) this.unsubscribeFromHistory();
  }

  handleLocationChange = (location) => {
    // Do something with the location
  }

  render() {
    // Render the rest of the application with its routes
  }
}

Not sure if this is the right way to do it in V4, but I didn't find any other extensibility points on the router itself, so this seems to work instead. Hope that helps.

Edit: Perhaps you could also achieve the same goal by wrapping <Route /> in your own component and using something like componentWillUpdate to detect location changes.

Upvotes: 10

Related Questions