@ibm/mobx-react-router
AKeep your MobX state in sync with react-router via a RouterStore.
Install
agr install @ibm/mobx-react-router --target codexWrites 1 file into AGENTS.md, pinned to git-de89eb63.
- AGENTS.md
Document
AGENTS.md
This file provides guidance to agents when working with code in this repository.
Testing
- Jest uses
jest-jasmine2test runner (not default circus) - specified in package.json - Tests must be in
__test__/directory (configured in jest.roots) - Custom jasmine matcher
toEqualLocationdefined in sync.spec.js for location comparisons
Code Style
- ESLint uses
neostandardconfig with custom overrides - No space before function parens:
function()notfunction () - Semicolons required (enforced at warning level)
- Camelcase not enforced (disabled)
no-return-assigndisabled (allowsreturn x = ypattern)
Build
- Webpack builds UMD bundle with
mobxas external dependency - Entry point is
index.js(not src/index.js) - Use
MINIFY=1env var to create minified build - Library exports as
MobxReactRouterglobal
MobX Integration
- RouterStore uses
makeAutoObservablewithautoBind: trueoption - Store location updates via private
_updateLocationmethod (not direct assignment) syncHistoryWithStoreaddssubscribe/unsubscribemethods to history object (non-standard history API extension)
Repository README
Describes IBM/mobx-react-router as a whole, which may contain artifacts other than this one. Where this artifact had no useful description of its own, its summary was taken from here.
mobx-react-router
โ ๏ธ Important: The NPM location of this repository has changed. Use
@ibm/mobx-react-routerinstead of the deprecatedmobx-react-router.
Keep your MobX state in sync with react-router via a RouterStore.
Router location state is observable, so any references to it in MobX
components will cause the component to re-render when the location changes.
Very much inspired by (and copied from) react-router-redux.
Features
- ๐ Keeps MobX state in sync with react-router
- ๐ฆ Observable router location for automatic component re-renders
- ๐ฏ Simple API with familiar history methods (push, replace, go, back, forward)
- ๐ Full TypeScript support included
- โก Compatible with React Router v6
- ๐ช Works with both class and functional components
Why Use This?
If you're using MobX for state management in your React application, mobx-react-router provides seamless integration with react-router. Instead of managing routing state separately, you can:
- Access routing state in MobX stores - Use
location.pathname,location.search, etc. in your business logic - Trigger navigation from stores - Call
push(),replace(), etc. directly from your MobX actions - Automatic re-renders - Components automatically update when route changes, thanks to MobX observables
- Centralized state - Keep all application state, including routing, in one place
Prerequisites
- React 16.8 or higher
- MobX 6.3.2 or higher
- React Router 6.14.2 or higher
Note: This branch (master) is for use with react-router v6. For react-router v5, check the v5 branch.
Installation
npm install --save @ibm/mobx-react-router
โ ๏ธ Deprecation Notice: The package
mobx-react-routeris deprecated. Use@ibm/mobx-react-routerinstead.
If you haven't installed the peer dependencies yet:
npm install --save mobx mobx-react react-router
Quick Start
Here's a minimal example to get you started:
import { createBrowserHistory } from 'history';
import { RouterStore, syncHistoryWithStore } from '@ibm/mobx-react-router';
const browserHistory = createBrowserHistory();
const routingStore = new RouterStore();
const history = syncHistoryWithStore(browserHistory, routingStore);
// Use routingStore.location in your components
// Use history with <Router location={routingStore.location} navigator={history}>
Usage
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createBrowserHistory } from 'history';
import { Provider } from 'mobx-react';
import { RouterStore, syncHistoryWithStore } from '@ibm/mobx-react-router';
import { Router } from 'react-router';
import App from './App';
const browserHistory = createBrowserHistory();
const routingStore = new RouterStore();
const stores = {
// Key can be whatever you want
routing: routingStore,
// ...other stores
};
const history = syncHistoryWithStore(browserHistory, routingStore);
ReactDOM.render(
<Provider {...stores}>
<Router location={routingStore.location} navigator={history}>
<App />
</Router>
</Provider>,
document.getElementById('root')
);
App.js
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
@inject('routing')
@observer
export default class App extends Component {
render() {
const { location, push, back } = this.props.routing;
return (
<div>
<span>Current pathname: {location.pathname}</span>
<button onClick={() => push('/test')}>Change url</button>
<button onClick={() => back()}>Go Back</button>
</div>
);
}
}
Check our live example with Vite.js.
HashRouter
You can replace history/createBrowserHistory with history/createHashHistory in the example above to use hash routes instead of HTML5 routing.
Troubleshooting
Routes not updating correctly when URL changes
There is a known issue with React Router 4 and MobX (and Redux) where "blocker" components like those
created by @observer (and @connect in Redux) block react router updates from propagating down the
component tree.
To fix problems like this, try wrapping components which are being "blocked" with React Router's withRouter higher
order component should help, depending on the case.
API
RouterStore
const store = new RouterStore();
A router store instance has the following properties:
Properties
-
location(observable) - The current location object from historypathname- The path of the URLsearch- The URL query stringhash- The URL hash fragmentstate- Location-specific statekey- Unique identifier for this location
-
history- Raw history API object for advanced usage
Methods
The store provides the following history navigation methods:
-
push(path: string | object)- Navigate to a new location, adding to history stackroutingStore.push('/users/123'); routingStore.push({ pathname: '/users', search: '?id=123' }); -
replace(path: string | object)- Replace current location without adding to historyroutingStore.replace('/login'); -
go(n: number)- Move n steps in history (negative for backwards)routingStore.go(-2); // Go back 2 pages -
back()- Go back one page (equivalent togo(-1))routingStore.back(); -
forward()- Go forward one page (equivalent togo(1))routingStore.forward();
syncHistoryWithStore(history, store)
Synchronizes a history instance with a RouterStore.
Parameters
history- A history object (fromcreateBrowserHistory,createHashHistory, etc.)store- An instance ofRouterStore
Returns
An enhanced history object with the following additional methods:
-
subscribe(listener: Function): UnsubscribeFunctionSubscribes to any changes in the store'slocationobservable. Returns: An unsubscribe function which destroys the listenerconst unsubscribeFromStore = history.subscribe((location, action) => { console.log(`Navigated to ${location.pathname}`); }); history.push('/test1'); // Logs: "Navigated to /test1" unsubscribeFromStore(); // Stop listening history.push('/test2'); // No log -
unsubscribe(): voidUn-syncs the store from the history. The store will no longer update when the history changes.history.unsubscribe(); // Store no longer updates when history changes
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests in watch mode
npm run test-watch
# Lint code
npm run lint
Trustgrade A
- passBody integrity
Whether the stored document is plausibly the kind of file the artifact declares, rather than something fetched by mistake.
- passType matchnot applicable to this artifact type
Whether the artifact is really the kind of thing its metadata claims it is.
- passFreshness
How long since the source repository was last pushed to.
- passPrompt injection
Scans the artifact's own text for instructions aimed at your agent rather than at you.
- passLicense
Whether the source repository declares an SPDX license permissive enough to redistribute.
How the grade is calculated
Each check contributes 0 points when it passes, 1 when it warns, and 2 when it fails. The total maps to a letter:
- Aevery check passed
- Bone warning
- Ctwo warnings
- Dprompt injection or body integrity failed, or three warnings
- Fone of those failed, and something else is wrong
These are automated hygiene checks, not a security audit, and not a dependency or vulnerability scan. A grade of A means nothing was flagged โ not that the artifact is safe.
Versions
git-de89eb63230d2026-08-06