Skip to content

Instantly share code, notes, and snippets.

@garth
Last active November 29, 2018 10:22
Show Gist options
  • Save garth/ef9d18a1f64c87afaeebf8c0b99c82f1 to your computer and use it in GitHub Desktop.
Save garth/ef9d18a1f64c87afaeebf8c0b99c82f1 to your computer and use it in GitHub Desktop.
A simple router using page.js and applied using react hooks
import React, { useState } from 'react'
import { routes } from './routes'
import { useRouter } from './router-hook'
const App: React.StatelessComponent = () => {
const route = useRouter(routes)
return (
<div>
<h1>{route.name}</h1>
</div>
)
}
export default App
import page from 'page'
import { useState, useEffect } from 'react'
const rawUrl = Symbol('rawUrl')
export type RouteToString = (params: RouteParams | typeof rawUrl) => string
export interface RouteParams {
[name: string]: string
}
export interface Routes {
[name: string]: string | RouteToString
}
export interface Route {
name: string
params: RouteParams
}
export const useRouter = (routes: Routes): Route => {
const [route, setRoute] = useState({ name: 'loading', params: {} })
useEffect(() => {
Object.keys(routes).forEach(name => {
const path = routes[name]
page(typeof path === 'function' ? path(rawUrl) : path, ({ params }) => {
setRoute({ name, params })
})
})
page.start({})
return () => {
page.stop()
}
}, [])
return route
}
export const route = (url: string, params: RouteParams | typeof rawUrl = {}) => {
if (params === rawUrl) {
return url
}
const parts: string[] = []
for (const part of url.split('/')) {
const matches = /^:(.+?)(\?)?$/.exec(part)
if (matches) {
const paramValue = params[matches[1]]
if (paramValue !== undefined) {
parts.push(`${paramValue}`)
} else if (matches[2] === '?') {
break
} else {
parts.push('')
}
} else {
parts.push(part)
}
}
return parts.join('/')
}
import { route } from './router-hook'
export const routes = {
user: (params: { id: string }) => route('/user/:id', params),
faq: '/faq',
login: '/login',
notFound: '*'
}
@garth
Copy link
Author

garth commented Nov 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment