URL persistence layer for MobX State Machine Router
npm install @mobx-state-machine-router/url-persistence> URL synchronization for MobX State Machine Router with hash/browser history support





- Hash Routing — Works on any static host (GitHub Pages, S3, Netlify, etc.)
- Browser History — Clean URLs with proper server configuration
- Query Parameters — Automatically syncs params to URL
- Deep Linking — Users can bookmark and share URLs
- Back/Forward — Full browser history support
- Custom Serializers — Handle complex types (arrays, objects, booleans)
``bash`
npm install @mobx-state-machine-router/url-persistence @mobx-state-machine-router/core history mobx
`typescript
import MobxStateMachineRouter, { TStates } from '@mobx-state-machine-router/core';
import URLPersistence from '@mobx-state-machine-router/url-persistence';
// Define states and actions as string literal types
type State = 'home' | 'products' | 'product-detail';
type Action = 'go-products' | 'view-product' | 'go-home';
type Params = {
productId?: string;
category?: string;
search?: string;
};
// Add url to each state
const states: TStates
home: {
actions: { 'go-products': 'products' },
url: '/',
},
products: {
actions: {
'go-home': 'home',
'view-product': 'product-detail',
'go-products': 'products', // Self-transition for param updates
},
url: '/products',
},
'product-detail': {
actions: { 'go-products': 'products' },
url: '/product',
},
};
// Create router with URL persistence
const router = MobxStateMachineRouter
states,
currentState: { name: 'home', params: {} },
persistence: URLPersistence(),
});
// Navigation now updates the URL!
router.emit('go-products');
// URL: /#/products
router.emit('view-product', { productId: '123' });
// URL: /#/product?productId=123
router.emit('go-products', { category: 'electronics', search: 'phone' });
// URL: /#/products?category=electronics&search=phone
`
Creates a URL persistence layer.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| history | History | createHashHistory() | History instance |serializers
| | ISerializers | {} | Custom param serializers |
`typescript
import { createBrowserHistory, createHashHistory, createMemoryHistory } from 'history';
// Hash history (default) - works everywhere, no server config needed
URLPersistence();
URLPersistence({ history: createHashHistory() });
// Browser history - cleaner URLs, requires server config for direct access
URLPersistence({ history: createBrowserHistory() });
// Memory history - useful for testing or SSR
URLPersistence({ history: createMemoryHistory() });
`
Handle complex param types:
`typescript`
URLPersistence({
serializers: {
// Boolean
isActive: {
getter: (value) => value === 'true',
setter: (value) => String(value),
},
// Array
tags: {
getter: (value) => JSON.parse(decodeURIComponent(value)),
setter: (value) => encodeURIComponent(JSON.stringify(value)),
},
// Number
page: {
getter: (value) => parseInt(value, 10),
setter: (value) => String(value),
},
},
});
``
/#/[state-url]?[param1]=[value1]&[param2]=[value2]
| URL | State | Params |
|-----|-------|--------|
| /#/ | home | {} |/#/products
| | products | {} |/#/products?category=electronics
| | products | { category: 'electronics' } |/#/product?productId=123
| | product-detail | { productId: '123' } |
To update query parameters without changing state, add a self-transition:
`typescript`
products: {
actions: {
'go-products': 'products', // Self-transition
// ... other actions
},
url: '/products',
},
Then emit with new params:
`typescript`
// Update filters on the same page
router.emit('go-products', { category: 'electronics' });
`tsx
import { observer } from 'mobx-react-lite';
const ProductsPage = observer(() => {
const { category, search } = router.currentState.params;
const handleCategoryChange = (cat: string) => {
router.emit('go-products', { ...router.currentState.params, category: cat });
};
return (
- MobX 4.x, 5.x, or 6.x
- history 5.x
- Works with React, React Native (with memory history), Vue, or vanilla JS
- @mobx-state-machine-router/core — Core router package
MIT © Anzor Bashkhaz