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/