πββοΈ Made by @thekitze
- π« React Academy - Interactive React and GraphQL workshops
- π Twizzy - A standalone app for Twitter DM
- π» Sizzy - A tool for testing responsive design on multiple devices at once
- π€ JSUI - A powerful UI toolkit for managing JavaScript apps
π How to decouple state and UI - a.k.a. you donβt need componentWillMount
- Decoupled state from UI
- Central route configuration
- URL changes are triggering changes directly in the store, and vice-versa
- No need to use component lifecycle methods like
componentWillMountto fetch data or trigger a side effect in the store - Supported callbacks for the routes are:
beforeEnter,onEnter,beforeExit,onExit. All of the callbacks receiveroute,params,store, andqueryParamsas parameters. If thebeforeExitorbeforeEntermethods returnfalsethe navigation action will be prevented. - The current URL params and query params are accessible directly in the store
store.router.params/store.router.queryParamsso basically they're available everywhere without any additional wrapping or HOC. - Navigating to another route happens by calling the
goTomethod on the router store, and the changes in the url are reflected automatically. So for example you can callrouter.goTo(routes.book, {id:5, page:3})and after the change is made in the store, the URL change will follow. You never directly manipulate the URL or the history object. <Link>component which also populates the href attribute and works withmiddle clickorcmd/ctrl + click- Typescript support (Converted to typescript by thdk)
- Hash-based routing (using paths like
/#/foo/bar) support
import React, {createContext} from 'react'; import ReactDOM from 'react-dom'; import {MobxRouter, RouterStore, startRouter} from 'mobx-router'; import routes from 'config/routes'; //example mobx store export class AppStore { title = 'MobX Router Example App', user = null } export class RootStore { public router: RouterStore<RootStore>; public app: AppStore; constructor() { this.router = new RouterStore<RootStore>(this); this.app = new AppStore(); } } const store = new RootStore(); // Use React context to make your store available in your application const StoreContext = createContext({}); const StoreProvider = StoreContext.Provider; startRouter(routes, store); ReactDOM.render( <StoreProvider value={store}> <MobxRouter store={store}/> </StoreProvider>, document.getElementById('root') )/config/routes.js
import React from 'react'; //models import {Route} from 'mobx-router'; //components import Home from 'components/Home'; import Document from 'components/Document'; import Gallery from 'components/Gallery'; import Book from 'components/Book'; import UserProfile from 'components/UserProfile'; const routes = { home: new Route({ path: '/', component: <Home/> }), userProfile: new Route({ path: '/profile/:username/:tab', component: <UserProfile/>, onEnter: () => { console.log('entering user profile!'); }, beforeExit: () => { console.log('exiting user profile!'); }, onParamsChange: (route, params, store) => { console.log('params changed to', params); } }), gallery: new Route({ path: '/gallery', component: <Gallery/>, onEnter: (route, params, store, queryParams) => { store.gallery.fetchImages(); console.log('current query params are -> ', queryParams); }, beforeExit: () => { const result = confirm('Are you sure you want to leave the gallery?'); return result; } }), document: new Route({ path: '/document/:id', component: <Document/>, beforeEnter: (route, params, store) => { const userIsLoggedIn = store.app.user; if (!userIsLoggedIn) { alert('Only logged in users can enter this route!'); return false; } }, onEnter: (route, params) => { console.log(`entering document with params`, params); } }), book: new Route({ path: '/book/:id/page/:page', component: <Book/>, onEnter: (route, params, store) => { console.log(`entering book with params`, params); store.app.setTitle(route.title); } }) }; export default routes;mobx-router uses director behind the scenes. mobx-router exposes the director config object for you to pass your own configuration to director.
To do this you must pass a DirectorConfig object as third argument of startRouter method.
Hash based Routing | html5history
If you disable html5history option, mobx will fallback to hash based routing.
startRouter( routes, store, { // https://github.com/flatiron/director#configuration html5history: false, } );Not found (404) route | notfound
You can pass a function to notfound which will be called when you don't have any matching route for the current path.
startRouter( routes, store, { // https://github.com/flatiron/director#configuration notfound: () => store.router.goTo(YOUR_NOT_FOUND_ROUTE), } );