State-Based Routing with abstract-state-router

2015-06-22 17:59:02 +0100 by Alex R. Young

A few months ago I wrote a custom hash URL router for a React project. We've been trying to plug in a more generalised open source router, but dealing with the state in our particular application has proved problematic. Josh Duff sent in abstract-state-router (GitHub: TehShrike/abstract-state-router, License: WTFPL, npm: abstract-state-router), a general purpose routing library that isn't tied into any specific framework. Josh had been working with Angular, but wanted to use a routing library outside of Angular projects.

This is from Josh's post about the project - Why your webapp needs a state-based router:

I'm a child of the node/npm revolution, and as such I'm pretty framework-averse. I prefer disconnected modules that solve problems that I can compose myself.

I looked for similar libraries, but the only ones I found (react-router and Ember's router) are similarly tied to their chosen rendering/templating tools.

Built with help from ArtskydJ, abstract-state-router is heavily inspired by ui-router, intended to be used with whatever templating library you like. At the time of this writing, renderers have been set up for Ractive.JS, Riot, and virtual-dom - and it's not too difficult to implement new ones with your favorite template/dom manipulation library.

The API uses ideas from ui-router and Express: route names are parsed using ui-router's dot notation, and routes are parsed with a fork of path-to-regexp.

Here's a quick example:

var createStateRouter = require('abstract-state-router');
var stateRouter = createStateRouter(makeRenderer, rootElement, options);

  name: 'app.tab1',
  data: {},
  route: '/tab_1',
  template: '',
  resolve: function(data, parameters, cb) {
  }, activate: function(context) {
    document.getElementById('tab').innerText = context.content

In this example, the makeRenderer option is a function that returns an object with four properties: render, destroy, getChildElement, and reset. There's an example of this in the test helpers.

Once you've set up a router, you can browse to a specific state with stateRouter.go. The way state change is handling is documented in the readme in detail, but every state change destroys DOM elements that are no longer valid, and then creates the new states.

To my knowledge abstract-state-router is unique because it focuses on state and defining routes, so it's not tied to any specific framework. Josh said he's willing to help people hook it up to specific UI libraries, so if you want to use it but aren't sure how t implement the rendering code then he may help you out!