Skip to content

pzmosquito/mr-router5

Repository files navigation

mr-router5   npm version npm bundle size npm type definitions

mr-router5 uses Router5 together with MobX for your favorite React application.

  • router5 is an awesome framework and view library agnostic router.
  • MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming.

Why mr-router5

mr-router5 creates a minimal bridge between router5, MobX and React. When I say 'minimal bridge', I really mean it. Your React components stay untouched, there's no need to create HOC for your root App component. The global and route level payload makes the route transition more flexible and powerful.

Peer Dependencies

  • React >=16.8
  • router5 ^7 || ^8
  • mobx ^6
  • mobx-react-lite ^3

Installation

npm install --save mr-router5

Upgrade v3 to v4

v4 removes the RouteTree class, the upgrade should be straightforward.

// v3
import { RouteTree, routerStore, initMrRouter5 } from "mr-router5";

const routeTree = new RouteTree([...]);
const router = createRouter(routeTree.getRoutes(), {});
initMrRouter5(router, routeTree);

// v4
import { routerStore, toRoutes } from "mr-router5";

const routeViews = [...];
const router = createRouter(toRoutes(routeViews), {});
routeStore.init(router, routeViews);

Reference

Basic Usage

see router5 on how to create router instance.

import React from "react";
import { render } from "react-dom";
import createRouter from "router5";
import { RouteComponent, RouteView, routerStore, toRoutes } from "mr-router5";

// define components.
const Home = () => <div>'home' component</div>;
const UserNode = () => <div>'user' route node component</div>;
const UserList = () => <div>'user list' component</div>;
const UserView = () => <div>'user view' component</div>;

// define route views. NOTE, only flat routes are supported.
const routeViews = [
    new RouteView({name: "home", path: "/"}, Home),
    new RouteView({name: "users", path: "/users"}, UserNode),
    new RouteView({name: "users.list", path: "/list"}, UserList),
    new RouteView({name: "users.view", path: "/view"}, UserView),
];

// create router instance and initialize mr-router5.
const router = createRouter(toRoutes(routeViews), {});
routeStore.init(router, routeViews);

// create root route node.
const routeNodeName = ""; // THIS NAME MUST MATCH THE ROUTE NAME! (empty string for root route node)
const RootNode = () => (
    <div>
        <h2>Header</h2>
        <RouteComponent routeNodeName={routeNodeName} />
        <h4>Footer</h4>
    </div>
);

// start the router.
router.start(() => {
    render(<RootNode />, document.getElementById("app"));
});

payload

You can add payload to each route view, by setting extra and dataLoader. There are many ways to use them, one example would be middleware, see router5 middleware.

const routeViews = [
    new RouteView({name: "login", path: "/login"}, Login),
    new RouteView({name: "user", path: "/user"}, UserComponent)
        .setExtra("user", "John Doe")
        .setExtra("requireLogin", true)
        .setDataLoader("getUserDetail", (user) => ({ /* user details */ }))
];

// router5 middleware
router.useMiddleware((router) => (toState, fromState, done) => {
    // get route view of the toState
    const rv = routerStore.getRouteView(toState.name);
    
    // skip login check if 'requireLogin' is false.
    if (!rv.getExtra("requireLogin", false)) {
        done();
    }
    else {
        // check if user is logged in
        const isLoggedIn = true;
        if (isLoggedIn) {
            const user = rv.getExtra("user");
            const userDetail = rv.getDataLoader("getUserDetail")(user);
            done();
        }
        else {
            done({ redirect: { name: "login" } });
        }
    }
});

That's it. Enjoy routing.