Mithril's route API is predicated on the notion that all logic and view concerns are specific to a given route endpoint. In any significant application, this leads to a lot of flaky code duplication: most views share a lot of markup; some persistent application logic is route-agnostic; some logic needs to be run on every route. In these scenarios it makes more sense to treat the route as a data source, and mount a single top level component with a consolidated lifecycle that is guaranteed to have access to all route data.
mRouteStream
offers an interface concerned solely with the business of routing, allowing you to provide a list of routes and handle Mithril view logic separately. The return value of mRouteStream
is a stream which emits an array that matches the signature of onmatch
.
Signature:
const route = mRouteStream(defaultRoute, routes)
Argument | Type | Required | Default | Description |
---|---|---|---|---|
defaultRoute |
String |
No | '/' |
The default route - maps to the second argument of Mithril's m.route |
routes |
Array |
No | [':path...'] |
The routes, without endpoint mapping - the equivalent of running Object.keys on the third argument of Mithril's m.route |
returns | Stream |
A stream that emits an array conforming to Mithril's RouteResolver onmatch signature |
Example:
const route = mRouteStream( '/', [
'/',
'/about',
'/post/:postId',
'/:404...'
])
m.mount(document.body, {
oninit(){
// Centralised route parsing logic
route.map(([args, requestedPath]) => {
// Bind route data to state
Object.assign(this, {args, requestedPath})
// Flag a route-based redraw
this.routing = true
})
},
// Centralised route-based lifecycle logic
onupdate(){
// Infer route-based redraw
if(this.routing){
scrollTo(0, 0)
this.routing = false
}
},
// Single comprehensive view
view : vnode =>
vnode.state.args[404]
? m(NotFound, requestedPath) // High-level fork
: m(Layout, // Common elements defined once rather than copy-pasted across route endpoints
m(Header, vnode.state ), // Passing down route data for high-level components
/^(\/|\/about)$/.test(vnode.state.requestedPath)
? m(Page, vnode.state)
: vnode.state.args.post
? m(Post, Object.assign(
// Route data can be abstracted at any point
{ editing : /edit$/.test(vnode.state.requestedPath) },
vnode.state
))
)
})