Implementing a static route config and named routes on top of (react-router) at this point is like a 20 line ordeal. – Ryan Florence
Named routes are essential to keep route config DRY and prevent silly errors
due to typos. This feature was removed from react-router in 1.0 and I missed
it since then as many
others.
There're other libs dealing with named routes, some of them provide custom
Link, Route routes, some of them have more features to integrate with
express. Here's incomplete list of libs I considered before writing these
20 lines of code (and 200+ lines of other files to publish this package):
- https://github.com/adamziel/react-router-named-routes
- https://github.com/taion/use-named-routes
- https://github.com/alubbe/named-routes
yarn add named-urls
Create file with all routes in your application (e.g. routes.js). Use
named-urls/include to create namespaced group of routes with common prefix:
// routes.js
import { include } from 'named-urls'
export default {
// simple route
profile: '/profile',
// route with params
article: '/article/:articleId',
// route with optional params
messages: '/messages/:messageId?',
// Routes with common path prefix
auth: include('/auth', {
// Absolute url (ignore /auth prefix)
login: '/login/',
// Relative urls (prefixed with /auth)
passwordReset: 'password/reset/',
passwordVerify: 'password/verify/',
}),
// Routes with params
messages: include('/messages', {
all: '',
unread: 'unread/'
// nesting of includes is allowed
detail: include(':messageId/', {
show: '',
edit: 'edit/',
comments: 'comments/',
})
})
}Use routes in Route component from react-router-dom:
// App.js
import * as React from 'react'
import { Switch, Route } from 'react-router-dom'
import routes from './routes'
import * as scenes from './scenes'
function App() {
return (
<Switch>
<Route path={routes.profile} component={scenes.Profile />
<Route path={routes.auth.login} component={scenes.auth.Login />
// ...
<Route path={routes.messages.unread} component={scenes.messages.Unread />
<Route path={routes.messages.detail.show} component={scenes.messages.Detail />
</Switch>
)
}Routes with parameters can be formatted using reverse function:
// Navigation.js
import * as React from 'react'
import { Link } from 'react-router'
import { reverse } form 'named-urls'
function Navigation({ messages }) {
return (
<ul>
<li><Link to={routes.profile}>Profile</Link></li>
// ...
// Use reverse to replace params in route pattern with values
{messages.map(message =>
<li key={message.id}>
<Link to={reverse(routes.messages.detail.show, { messageId: message.id })}>
Profile
</Link>
</li>
)}
</ul>
)
}Patterns ending with slash are always reversed to URL with ending slash and vice versa: Paterns without ending slash are always reserved to URL without endlish slash:
// pattern with ending slash
reverse('pattern/:optional?', { optional: 42 }) // pattern/42
reverse('pattern/:optional?') // pattern
// pattern without ending slash
reverse('pattern/:optional?/', { optional: 42 }) // pattern/42/
reverse('pattern/:optional?/') // pattern/