{"id":13566982,"url":"https://github.com/kitze/mobx-router","last_synced_at":"2025-05-16T03:02:13.702Z","repository":{"id":37271577,"uuid":"68822229","full_name":"kitze/mobx-router","owner":"kitze","description":"A simple router for MobX + React apps","archived":false,"fork":false,"pushed_at":"2023-05-25T15:06:12.000Z","size":1211,"stargazers_count":508,"open_issues_count":29,"forks_count":68,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-05-04T13:03:25.095Z","etag":null,"topics":["history","hooks","lifecycle-events","mobx","react","router"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kitze.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-09-21T13:55:53.000Z","updated_at":"2025-03-23T18:18:59.000Z","dependencies_parsed_at":"2024-01-15T02:30:13.579Z","dependency_job_id":"2978d876-d054-4e57-aee6-998c8f22c707","html_url":"https://github.com/kitze/mobx-router","commit_stats":{"total_commits":121,"total_committers":16,"mean_commits":7.5625,"dds":0.5619834710743802,"last_synced_commit":"d8b65c6b7253b233d3e4ef01c7c6535e1d45339d"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitze%2Fmobx-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitze%2Fmobx-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitze%2Fmobx-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitze%2Fmobx-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kitze","download_url":"https://codeload.github.com/kitze/mobx-router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254328385,"owners_count":22052632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["history","hooks","lifecycle-events","mobx","react","router"],"created_at":"2024-08-01T13:02:20.858Z","updated_at":"2025-05-16T03:02:13.563Z","avatar_url":"https://github.com/kitze.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Awesome MobX"],"sub_categories":["Related projects and utilities"],"readme":"### 🙋‍♂️ Made by [@thekitze](https://twitter.com/thekitze)\n\n### Other projects:\n- 🏫 [React Academy](https://reactacademy.io) - Interactive React and GraphQL workshops\n- 💌 [Twizzy](https://twizzy.app) - A standalone app for Twitter DM\n- 💻 [Sizzy](https://sizzy.co) - A tool for testing responsive design on multiple devices at once\n- 🤖 [JSUI](https://github.com/kitze/JSUI) - A powerful UI toolkit for managing JavaScript apps\n\n\u003ca href=\"https://zerotoshipped.com\"\u003e\u003cimg style=\"width:450px\" src=\"https://i.ibb.co/WKQPDv5/twitter-image.jpg\" alt=\"Zero To Shipped\"\u003e\u003c/a\u003e\n\n---\n\n# 〽️ MobX Router\n\n### Example usage\n* [Demo project](http://mobx-router-example.netlify.com/)\n* [Demo project repo](https://github.com/kitze/mobx-router-example)\n* [Demo project repo with typescript](https://github.com/thdk/mobx-router-typescript-example)\n\n## Inspiration\n[📖 How to decouple state and UI - a.k.a. you don’t need componentWillMount](https://medium.com/@mweststrate/how-to-decouple-state-and-ui-a-k-a-you-dont-need-componentwillmount-cc90b787aa37#.k9tvf5nga)\n\n## Features\n- Decoupled state from UI\n- Central route configuration\n- URL changes are triggering changes directly in the store, and vice-versa\n- No need to use component lifecycle methods like `componentWillMount` to fetch data or trigger a side effect in the store\n- Supported callbacks for the routes are: `beforeEnter`, `onEnter`, `beforeExit`, `onExit`. All of the callbacks receive `route`, `params`, `store`, and `queryParams` as parameters. If the `beforeExit` or `beforeEnter` methods return `false` the navigation action will be prevented.\n- The current URL params and query params are accessible directly in the store `store.router.params` / `store.router.queryParams` so basically they're available everywhere without any additional wrapping or HOC.\n- Navigating to another route happens by calling the `goTo` method on the router store, and the changes in the url are reflected automatically. So for example you can call `router.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.\n- `\u003cLink\u003e` component which also populates the href attribute and works with `middle click` or `cmd/ctrl + click`\n- Typescript support (Converted to typescript by [thdk](https://github.com/thdk))\n- Hash-based routing (using paths like `/#/foo/bar`) support\n\n### Implementation\n```js\nimport React, {createContext} from 'react';\nimport ReactDOM from 'react-dom';\n\nimport {MobxRouter, RouterStore, startRouter} from 'mobx-router';\nimport routes from 'config/routes';\n\n//example mobx store\nexport class AppStore {\n    title = 'MobX Router Example App',\n    user = null\n}\n\nexport class RootStore {\n    public router: RouterStore\u003cRootStore\u003e;\n    public app: AppStore;\n\n    constructor() {\n        this.router = new RouterStore\u003cRootStore\u003e(this);\n        this.app = new AppStore();\n    }\n}\n\nconst store = new RootStore();\n\n// Use React context to make your store available in your application\nconst StoreContext = createContext({});\nconst StoreProvider = StoreContext.Provider;\n\nstartRouter(routes, store);\n\nReactDOM.render(\n  \u003cStoreProvider value={store}\u003e\n  \t\u003cMobxRouter store={store}/\u003e\n  \u003c/StoreProvider\u003e, document.getElementById('root')\n)\n```\n\n### Example config\n\n/config/routes.js\n\n```js\nimport React from 'react';\n\n//models\nimport {Route} from 'mobx-router';\n\n//components\nimport Home from 'components/Home';\nimport Document from 'components/Document';\nimport Gallery from 'components/Gallery';\nimport Book from 'components/Book';\nimport UserProfile from 'components/UserProfile';\n\nconst routes = {\n  home: new Route({\n    path: '/',\n    component: \u003cHome/\u003e\n  }),\n  userProfile: new Route({\n    path: '/profile/:username/:tab',\n    component: \u003cUserProfile/\u003e,\n    onEnter: () =\u003e {\n      console.log('entering user profile!');\n    },\n    beforeExit: () =\u003e {\n      console.log('exiting user profile!');\n    },\n    onParamsChange: (route, params, store) =\u003e {\n      console.log('params changed to', params);\n    }\n  }),\n  gallery: new Route({\n    path: '/gallery',\n    component: \u003cGallery/\u003e,\n    onEnter: (route, params, store, queryParams) =\u003e {\n    \tstore.gallery.fetchImages();\n    \tconsole.log('current query params are -\u003e ', queryParams);\n    },\n    beforeExit: () =\u003e {\n      const result = confirm('Are you sure you want to leave the gallery?');\n      return result;\n    }\n  }),\n  document: new Route({\n    path: '/document/:id',\n    component: \u003cDocument/\u003e,\n    beforeEnter: (route, params, store) =\u003e {\n      const userIsLoggedIn = store.app.user;\n      if (!userIsLoggedIn) {\n        alert('Only logged in users can enter this route!');\n        return false;\n      }\n    },\n    onEnter: (route, params) =\u003e {\n      console.log(`entering document with params`, params);\n    }\n  }),\n  book: new Route({\n    path: '/book/:id/page/:page',\n    component: \u003cBook/\u003e,\n    onEnter: (route, params, store) =\u003e {\n      console.log(`entering book with params`, params);\n      store.app.setTitle(route.title);\n    }\n  })\n};\nexport default routes;\n```\n\n### Custom director configuration\n\n*mobx-router* uses [director](https://github.com/flatiron/director) behind the scenes. mobx-router exposes the director config object for you to pass your own configuration to director.\n\nTo do this you must pass a `DirectorConfig` object as third argument of `startRouter` method.\n\n**Hash based Routing | html5history**\n\nIf you disable html5history option, mobx will fallback to hash based routing. \n```js\nstartRouter(\n  routes, \n  store, \n  {\n    // https://github.com/flatiron/director#configuration\n    html5history: false,\n  }\n);\n```\n\n**Not found (404) route | notfound**\n\nYou can pass a function to `notfound` which will be called when you don't have any matching route for the current path.\n\n```js\nstartRouter(\n  routes, \n  store, \n  {\n    // https://github.com/flatiron/director#configuration\n    notfound: () =\u003e store.router.goTo(YOUR_NOT_FOUND_ROUTE),\n  }\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkitze%2Fmobx-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkitze%2Fmobx-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkitze%2Fmobx-router/lists"}