Skip to main content

Extensions

router

router is a specific module that automatically handles frontend routing and browser history.

Getting started

// store.js
// --------------------------
import Store from '@perseid/store';
import router from '@perseid/store/extensions/router';

const store = new Store();
store.register('router', router([
'/home',
'/blog',
// Add all your app's routes here...
]));
export default store;

// main.js
// --------------------------
import store from './store.js';

store.subscribe('router', (context) => console.log(context));

As any other @perseid/store modules, router must be registered into the store using the register method. As soon as it is done, any subscription to that module will receive the current routing context, containing useful information about current route.

{
host: 'mydomain.com', // Current app domain
params: { id: '125' }, // Route parameters
path: '/user/125', // Full route path (request URI)
protocol: 'http', // URL scheme (HTTP/HTTPS/...)
query: { q: 'ok' }, // Parsed query parameters (if any)
route: '/user/:id', // Route pattern that matched current URL
}

Routing

When initializing the router module, a list of routes is expected in argument (see above). This list is actually a set of patterns that will be matched against the current URL. The matching process is based on the exact same logic as for the expressjs framework (using path-to-regexp npm package), which means you can define dynamic parameters in those routes, regular expressions, and so on. These dynamic info will be placed into the params key in the routing context.

Let's take an example. Imagine we initialized router this way.

store.register('router', router([
'/',
'/blog',
'/blog/posts/:name',
]));

We are currently browsing the URL https://mydomain.com/blog/posts/@perseid/store-is-life

router will thus generate the following routing context.

{
host: 'mydomain.com',
params: { name: '@perseid/store-is-life' },
path: '/blog/posts/@perseid/store-is-life',
protocol: 'https',
query: {},
route: '/blog/posts/:name', // `null` if no route matches the URL
}

One of the most interesting features of router is that you can navigate to any route seamlessly, without reloading the page, loosing current state or performing complex processing. Just call the NAVIGATE mutation.

store.mutate('router', 'NAVIGATE', '/my/next/page');

router will automatically manage window's history, pushing a new state. The routing context will also be re-computed and dispatched to all subscriptions. It is especially useful when you want to track navigation, or to lazy load your app's pages over browsing, for instance, to improve initial page load. User can then go back and forth through his browser history as he usually would without breaking any logic or reloading page.