A reactive wrapper around Page JS
The URL is like any other state
I have decided to deprecate this project, the reason being that we have developed addressbar and url-mapper. These projects encourages to move routing to something else than deciding what views/components to render. Typically this is related to producing state instead, but I think we can do a lot of cool stuff with urls. One example of what these projects has made us able to do is shown in cerebral-router.
When the router moved to the frontend it has been given a lot of different jobs. Keep track of and parse the current url, control the VIEW layer and often do data-fetching and handling transition states. The reactive-router is going back to the roots of what a router does, and that is pass a URL request to the controller layer of your application.
Some more info
Your VIEW layer should not care about what the URL is, it should care about what state your application is in
The way to think about the reactive-router is this:
/inbox
which puts your application in {currentFolder: 'inbox'}
currentFolder
stateWhat this means is that you stop thinking about your UI as a reflection of the URLs, because it does not matter. What matters is the state you want to put your application in. A URL is just a way to trigger some state, it being setting what components to render, what filters to set, what item in a list to highlight etc.
First of all this allows you to trigger a url change by just changing the "url" state inside your state store. It also allows you to define what a url-change actually means. It does not have to be changing out components, it could be highlighting something in a list or trigger some animation.
reactive-router is a wrapper around pagejs, a neat little routing library built by visionmedia.
import ReactiveRouter from 'reactive-router';
import state from './state.js';
// state can be a store, controller, actions or whatever is responsible
// for changing the state of your app. This example is with a state store
// Actions like these can be a lot more generic, but it is just to show you
const homeRouted = function (context) {
state.set('url', context.path);
state.set('currentPage', 'home');
};
const messageRouted = function (context) {
state.set('url', context.path);
state.set('currentPage', 'messages');
state.set('currentMessage', context.params.id);
};
const errorRouted = function (context) {
state.set('url', context.path);
state.set('currentPage', 'error');
};
/*
ROUTER
The way you define routes is changed. Pass one object to define all routes.
Second argument is any Page JS options
*/
const router = ReactiveRouter({
'/home': homeRouted,
'/messages/:id': messageRouted,
'/error': errorRouted
}, {
hashbang: true
});
// Listen to state changes and set the url
state.on('change', function (state) {
router.set(state.url);
// or silently set, will not trigger the callback
router.setSilent(state.url);
});
If you are familiar with React, you can compare this to an input. Even though the input/router is what caused the change, we want to store the state (value/url) and bring it right back to the input/router. The reason is that now we can manually change the input/router value/url inside our state store and it will be reflected in the UI, as you can see an examples of with the actions above. To change a url you can trigger your own "change url" signal, or just change the url normally with a hyperlink.
@State({currentPage: ['currentPage'])
const Comp = React.createClass({
render() {
switch (this.props.currentPage) {
case 'home':
return <Home/>;
case 'messages':
return <Messages/>
case 'error':
return <Error/>
}
}
});
const Comp = React.createClass({
render() {
return (
<a href="https://github.com/christianalfoni/reactive-router/blob/master/messages/123">Open message 123</a>
);
}
});
Now you can change the route from within your actions/controller and the router will react to that.
import ajax from './state.js';
import state from './state.js';
const someAction = function () {
ajax.post('/something')
.resolve(function (data) {
state.set('data', data);
state.set('url', '/data');
})
.catch(function (error) {
state.set('error', error);
state.set('url', '/error');
});
};