Lately I’ve been doing some front-end work in JavaScript using React and Redux.

As our application has grown, we’ve found it necessary to add client-side routing. For that, we’ve adopted react-router and react-router-redux (formerly redux-simple-router).

As an application grows, the route definitions can start to get out of hand. You’ll eventually want to start extracting routes into separate pieces. Here are some steps you can take to separate your routes.

All Together

When you first get started with react-router, you’ll probably keep all of your routes together in one place, just like it shows in the documentation. Here’s the example from the react-router README:

All Routes in One Place
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="about" component={About}/>
<Route path="users" component={Users}>
<Route path="/user/:userId" component={User}/>
</Route>
<Route path="*" component={NoMatch}/>
</Route>
</Router>
), document.body)

Move Routes Into Their Own File

As you add more routes, you might think about splitting them up. The first step you can take is to move the routes into a separate file, away from the Router itself. Note that I’m using some ES2015 features.

Move Routes to Their Own File
// routes.js
const routes = (
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="users" component={Users}>
<Route path="/user/:userId" component={User} />
</Route>
<Route path="*" component={NoMatch} />
</Route>
)
export default routes
// original file
import routes from './routes'
render((
<Router history={browserHistory} routes={routes} />
), document.body)

The children of the router are just a prop, so we can pass them in just like any other prop in React/JSX. Here, I’ve used the routes prop instead of children because I find it reads better, but routes is just an alias of children so choose the one you like best.

Route also has a children prop (but not the routes alias), so you can repeat this decomposition at any layer of your routing tree.

Split Routes Into Multiple Files

After further growth in your routes, you might want to break off different sections of your routes. As I mentioned above, you can extract child routes at any level of the routing tree and pass them in as props to any Route you have defined.

But what if you want to split some of the routes away from their siblings?

As an example, let’s split the user-related routes into their own file. We want to keep the about and * routes where they are.

Split Routes Into Multiple Files
// userRoutes.js
const userRoutes = (
<Route path="users" component={Users}>
<Route path="/user/:userId" component={User} />
</Route>
)
export default userRoutes
// routes.js
import userRoutes from './userRoutes'
const routes = (
<Route path="/" component={App}>
<Route path="about" component={About} />
{userRoutes}
<Route path="*" component={NoMatch} />
</Route>
)
export default routes
// original file
import routes from './routes'
render((
<Router history={browserHistory} routes={routes} />
), document.body)

Here’s we’ve moved the entire users routing tree to its own file and then “spliced” it back into its original location using a JSX child expression. When I first tried this I was surprised that it worked, but the JSX transformation does the right thing.

Dynamic Loading

Once your application gets large enough, you might want to think about splitting it up into pieces and only loading the pieces that are actually needed. This includes the routes. If you have a large set of routes, you may not want or need all of them to be loaded at the same time. Fortunately, react-router supports this kind of dynamic loading of routes.

I won’t expand on the idea here, as it’s very well documented. See the Dynamic Routing section in the react-router documentation as well as the huge-apps example.

Conclusion

I find react-router to be an interesting library. It works for the very simple project where you only have a few routes, but can scale up to very large applications with full dynamic loading.

I’ve given you a few steps along this continuum. Choose the place that’s right for your application, and let me know if there are other patterns that I’m not aware of.