Keep your MobX state in sync with react-router via a RouterStore
npx @tessl/cli install tessl/npm-ibm--mobx-react-router@6.1.00
# MobX React Router
1
2
MobX React Router provides seamless integration between MobX observable state management and React Router by offering a RouterStore class that makes router location state observable, enabling MobX components to automatically re-render when navigation occurs. The library includes a syncHistoryWithStore function that synchronizes browser history with the MobX store, providing navigation methods and subscription capabilities for location changes.
3
4
## Package Information
5
6
- **Package Name**: @ibm/mobx-react-router
7
- **Package Type**: npm
8
- **Language**: JavaScript (with TypeScript definitions)
9
- **Installation**: `npm install @ibm/mobx-react-router`
10
11
## Core Imports
12
13
```javascript
14
import { RouterStore, syncHistoryWithStore } from "@ibm/mobx-react-router";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { RouterStore, syncHistoryWithStore } = require("@ibm/mobx-react-router");
21
```
22
23
## Basic Usage
24
25
```javascript
26
import React from 'react';
27
import ReactDOM from 'react-dom';
28
import { createBrowserHistory } from 'history';
29
import { Provider } from 'mobx-react';
30
import { RouterStore, syncHistoryWithStore } from '@ibm/mobx-react-router';
31
import { Router } from 'react-router';
32
import App from './App';
33
34
// Create history and router store
35
const browserHistory = createBrowserHistory();
36
const routingStore = new RouterStore();
37
38
// Sync history with store
39
const history = syncHistoryWithStore(browserHistory, routingStore);
40
41
// Use in your app
42
const stores = {
43
routing: routingStore,
44
// ...other stores
45
};
46
47
ReactDOM.render(
48
<Provider {...stores}>
49
<Router location={routingStore.location} navigator={history}>
50
<App />
51
</Router>
52
</Provider>,
53
document.getElementById('root')
54
);
55
```
56
57
## Architecture
58
59
MobX React Router bridges the gap between MobX observable state management and React Router navigation through a simple yet powerful architecture:
60
61
- **RouterStore**: A MobX observable class that holds router state (`location` and `history`) and provides navigation methods
62
- **syncHistoryWithStore**: A synchronization function that creates bidirectional binding between browser history and the RouterStore
63
- **Observable Location**: The router location becomes observable, triggering MobX component re-renders when navigation occurs
64
- **History Integration**: Maintains full compatibility with the history API while adding MobX reactivity
65
66
## Capabilities
67
68
### RouterStore
69
70
Observable MobX store that wraps router state and provides navigation methods.
71
72
```javascript { .api }
73
/**
74
* Observable MobX store for router state management
75
*/
76
class RouterStore {
77
/** Observable location object (initially null) */
78
location: Location | null;
79
80
/** History API object (set by syncHistoryWithStore) */
81
history: History | null;
82
83
/** Creates a new RouterStore instance with observable location and history properties */
84
constructor();
85
86
/** Navigate to new location using history.push */
87
push(location: string | Partial<Location>, state?: any): void;
88
89
/** Replace current location using history.replace */
90
replace(location: string | Partial<Location>, state?: any): void;
91
92
/** Navigate n steps in history using history.go */
93
go(n: number): void;
94
95
/** Navigate back one step using history.back */
96
back(): void;
97
98
/** Navigate forward one step using history.forward */
99
forward(): void;
100
101
/** Internal method for updating location state (called by syncHistoryWithStore) */
102
_updateLocation(newState: Location): void;
103
}
104
```
105
106
**Usage Example:**
107
108
```javascript
109
import { inject, observer } from 'mobx-react';
110
111
@inject('routing')
112
@observer
113
export default class App extends Component {
114
render() {
115
const { location, push, back } = this.props.routing;
116
117
return (
118
<div>
119
<span>Current pathname: {location.pathname}</span>
120
<button onClick={() => push('/test')}>Change url</button>
121
<button onClick={() => back()}>Go Back</button>
122
</div>
123
);
124
}
125
}
126
```
127
128
### syncHistoryWithStore
129
130
Synchronizes a history object with a RouterStore instance, creating bidirectional binding between browser history and MobX observable state.
131
132
```javascript { .api }
133
/**
134
* Synchronizes browser history with RouterStore
135
* @param history - A history object (from history package)
136
* @param store - A RouterStore instance
137
* @returns Enhanced history object with subscription methods
138
*/
139
function syncHistoryWithStore(
140
history: History,
141
store: RouterStore
142
): SynchronizedHistory;
143
144
interface SynchronizedHistory extends History {
145
/** Subscribe to location changes in the store */
146
subscribe(listener: (location: Location, action: string) => void): UnregisterCallback;
147
148
/** Unsubscribe from history updates (store will no longer update) */
149
unsubscribe(): void;
150
}
151
```
152
153
**Usage Examples:**
154
155
```javascript
156
import { createBrowserHistory } from 'history';
157
import { RouterStore, syncHistoryWithStore } from '@ibm/mobx-react-router';
158
159
const browserHistory = createBrowserHistory();
160
const routingStore = new RouterStore();
161
const history = syncHistoryWithStore(browserHistory, routingStore);
162
163
// Subscribe to location changes
164
const unsubscribe = history.subscribe((location, action) => {
165
console.log(`Navigated to ${location.pathname} via ${action}`);
166
});
167
168
// Navigate programmatically
169
history.push('/dashboard');
170
history.replace('/settings');
171
172
// Clean up subscription
173
unsubscribe();
174
175
// Completely unsubscribe from history updates
176
history.unsubscribe();
177
```
178
179
## Types
180
181
```javascript { .api }
182
/** Callback function for unregistering listeners */
183
type UnregisterCallback = () => void;
184
185
/** Location object from history package */
186
interface Location {
187
pathname: string;
188
search: string;
189
hash: string;
190
state?: any;
191
key?: string;
192
}
193
194
/** History object from history package */
195
interface History {
196
length: number;
197
action: string;
198
location: Location;
199
push(path: string | Partial<Location>, state?: any): void;
200
replace(path: string | Partial<Location>, state?: any): void;
201
go(n: number): void;
202
back(): void;
203
forward(): void;
204
listen(listener: (location: Location, action: string) => void): UnregisterCallback;
205
}
206
207
/** History listener function type */
208
type Listener = (location: Location, action: string) => void;
209
```
210
211
## Error Handling
212
213
This library delegates navigation to the underlying history object and does not throw its own errors. Error handling should follow the patterns established by the history package being used.
214
215
**MobX Considerations:**
216
- Location updates are handled through MobX observables using `makeAutoObservable` with `autoBind: true`
217
- If MobX strict mode is enabled, ensure location updates occur within MobX actions
218
- The `_updateLocation` method is called internally and should not be called directly by application code
219
- Navigation methods (`push`, `replace`, `go`, `back`, `forward`) delegate to the underlying history object
220
221
## Compatibility
222
223
- **React Router**: v6.14.2+
224
- **MobX**: v6.3.2+
225
- **History**: v5.3.0+ (peer dependency of React Router)
226
- **React**: Compatible with React Router's supported versions