npm.io
6.0.0 • Published 6 months ago

@mobx-state-machine-router/core

Licence
MIT
Version
6.0.0
Deps
0
Size
29 kB
Vulns
0
Weekly
0
Stars
5

@mobx-state-machine-router/core

Declarative, predictable routing powered by finite state machines and MobX

npm version npm downloads CI codecov license

Live Demo | GitHub

Why?

  • State Machine First — Define valid states and transitions. Invalid navigation is impossible by design.
  • MobX Powered — Reactive state updates with fine-grained re-rendering.
  • Type Safe — Full TypeScript support with inferred types.
  • Lightweight — ~3KB gzipped, zero dependencies (MobX is a peer dependency).
  • React Native Ready — Works without URLs out of the box.

Installation

npm install @mobx-state-machine-router/core mobx

Quick Start

import MobxStateMachineRouter, { TStates } from '@mobx-state-machine-router/core';

// 1. 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;
};

// 2. Define the state machine
const states: TStates<State, Action> = {
  home: {
    actions: { 'go-products': 'products' },
  },
  products: {
    actions: {
      'go-home': 'home',
      'view-product': 'product-detail',
    },
  },
  'product-detail': {
    actions: {
      'go-home': 'home',
      'go-products': 'products',
    },
  },
};

// 3. Create the router
const router = MobxStateMachineRouter<State, Params, Action>({
  states,
  currentState: { name: 'home', params: {} },
});

// 4. Navigate
router.emit('go-products');
console.log(router.currentState.name); // 'products'

router.emit('view-product', { productId: '123' });
console.log(router.currentState.params); // { productId: '123' }

Usage with React

import { observer } from 'mobx-react-lite';
import { router } from './router';

const App = observer(() => {
  const { name, params } = router.currentState;

  return (
    <div>
      <nav>
        <button onClick={() => router.emit('go-home')}>Home</button>
        <button onClick={() => router.emit('go-products')}>Products</button>
      </nav>

      {name === 'home' && <HomePage />}
      {name === 'products' && <ProductsPage />}
      {name === 'product-detail' && <ProductDetail id={params.productId} />}
    </div>
  );
});

API

MobxStateMachineRouter(options)

Creates a router instance.

Option Type Description
states TStates<S, A> State machine definition
currentState { name: S, params: P } Initial state (optional)
persistence IPersistence URL persistence layer (optional)
router.currentState

Observable object containing current state:

router.currentState.name   // Current state name
router.currentState.params // Current params object
router.emit(action, params?)

Emit an action to transition states:

router.emit('go-home');
router.emit('view-product', { productId: '123' });
router.destroy()

Clean up subscriptions (important when using persistence).

observeParam(router, property, paramName, callback)

Observe a specific param for changes:

import { observeParam } from '@mobx-state-machine-router/core';

observeParam(router, 'currentState', 'productId', (change) => {
  console.log('productId changed:', change.newValue);
});

Observing & Intercepting

import { observe, intercept } from 'mobx';

// Observe state changes
observe(router, 'currentState', ({ newValue }) => {
  console.log('Navigated to:', newValue.name);
});

// Intercept and guard navigation
intercept(router, 'currentState', (change) => {
  if (change.newValue.name === 'admin' && !isLoggedIn) {
    return { ...change, newValue: { name: 'login', params: {} } };
  }
  return change;
});

URL Persistence

For URL synchronization, install the companion package:

npm install @mobx-state-machine-router/url-persistence history

See @mobx-state-machine-router/url-persistence for details.

Compatibility

  • MobX 4.x, 5.x, or 6.x
  • React 16.8+ (for hooks) or React Native
  • TypeScript 4.x or 5.x (optional)

License

MIT Anzor Bashkhaz

Keywords