Hooking into Route Changes in React Router v4

by Zach Silveira • 

React Router v4 is coming up fast. The first beta was released this week which includes support for hooking into route changes. I needed the ability to run a couple things any time a route changed, so I came up with a simple component that runs as many things as I want when the url is updated.

A couple ideas of what to run on route changes:

  • We have a referral system that needs to check if there's a certain query parameter in the url.
  • setting a canonical url
  • Send a page view to google analytics on every page change.
  • Redirect users if they are not allowed on certain pages (ex a regular user hitting /admin)

Since the referral system came up, I decided it might be better to have a way to hook into these changes in a more general way.

Yes, I came up with this today, and yes it's a very easy thing to do!

After doing this I realized many people new to react router may be confused as to how this is done, so here's a quick guide on hooking into route changes!

Here's the component:

import { withRouter } from 'react-router'

@withRouter
export default class RouteChange extends React.Component {

  componentDidMount () {
    this.routeChanged()
  }

  componentDidUpdate (prevProps) {
    let { location: { pathname } } = this.props

    if (prevProps.location.pathname === pathname) return
    this.routeChanged()
  }

  routeChanged () {
    let { location, push, replace, actions } = this.props

    actions.forEach(action => {
      action(location, { push, replace })
    })
  }

  render () {
    return null
  }
}

Now create an actions file and register as many functions as you'd like that will be ran on route changes:

import referral from './referral'  
import redirectWrongUser from './redirect-wrong-user'

export default [  
  referral,
  redirectWrongUser
]

An example function might look like the referral code I made:

import qs from 'qs'  
import ReferralRequest from './referral-request'

export default ({ pathname, search }) => {  
  const requestParams = qs.parse(search)
  if (!requestParams.referrer) return
  ReferralRequest(requestParams)
}

And there you have it, a simple way to add in hooks on route changes! Let's add it right inside our top-level Router component:

import routeActions from './route-actions'

export default () => (  
  <BrowserRouter>
    <div>
      <RouteChange 
        actions={routeActions}
      />
      <Container />
    </div>
  </BrowserRouter>
)

zach.codes newsletter

If you liked this post, please consider subscribing to my semi-weekly newsletter!