Skip to content

Latest commit

 

History

History
172 lines (134 loc) · 5.21 KB

README.md

File metadata and controls

172 lines (134 loc) · 5.21 KB

named-urls

Simple named url patterns in Javascript


CircleCI Code Coverage PRs Welcome MIT License

Watch on GitHub Star on GitHub Tweet

Implementing a static route config and named routes on top of (react-router) at this point is like a 20 line ordeal. – Ryan Florence

Motivation

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):

Installation

yarn add named-urls

Quickstart

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>
   )
}

Ending slash

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/

License

MIT