Primary image for Using Crossing with React-Router

Using Crossing with React-Router

With the version 1.0 release of react-router, the named Route feature was dropped. In earlier versions, you were able to define each Route with a name parameter:

<Route path="/account/billing" name="account-billing" />

and link to the RouteHandler via:

<Link to="account-billing">Billing</Link>

This provided a way to avoid hard-coding URL patterns throughout application code. Starting with version 1.0, the named paths are not allowed. The to parameter only accepts a path; it isn’t as convenient to keep the code DRY. A solution is to use the crossing library, whose purpose is to resolve names or URL patterns from an object that you provide.

Here is what an example react-router-based application could look like that shows the use of crossing to keep URL patterns DRY. You can get a copy of the repository and run it yourself from https://github.com/lincolnloop/crossing-react-router-demo.

import React from 'react'
import { Route, Router, Link } from 'react-router'
import History from 'react-router/lib/BrowserHistory'
import Crossing from 'crossing'


/**
 * Define some URL paths and assign them to names
 */
const urlTable = {
  'user:detail': '/user/:id',
  'photos': '/photos'
}

/**
 * Create an instance of Crossing, overriding the param format to be compatible with 
 * what react-router expects
 */
const urls = new Crossing(new RegExp(':([A-Za-z0-9-_%]{1,})'))
urls.load(urlTable)

/**
 * Create two React components that will be displayed depending on which
 * route is active.
 *
 * We're using the new ES6 class syntax to keep the code terse. 
 * Since these are pure components, all we really need 
 * is to pass React something with a `render` method.
 */
class User {
  render () {
    return (
      <div>
        <div>
          User 123
          <Link to={urls.get('photos')}>Photos</Link>
        </div>
        Hey, it worked!
      </div>
    )
  }
}

/**
 * You can see in the `Link` elements, we're using the Crossing instance to obtain
 * URL paths dynamically using the name and passing any appropriate parameters.
 */
class Photos {
  render () {
    return (
      <div>
        <div>
          <Link to={urls.get('user:detail', 123)}>User 123</Link>
          Photos
        </div>
        Photos?
      </div>
    )
  }
}

/**
 * Define some routes for react-router. We're passing the patterns 
 * that include param placeholders.
 */
const routes = (
  <Route path='/'>
    <Route path={urlTable['user:detail']} component={User}/>
    <Route path={urlTable['photos']} component={Photos}/>
  </Route>
)


React.render(
  <Router history={new History}>{routes}</Router>,
  document.body
)
Brian Luft

About the author

Brian Luft

A Full-Stack developer by virtue of 15 years working with various types of companies and technologies; which is another way of saying he has no special skills. With a little sister unwilling to play D&D, he …