• Stars
    star
    111
  • Rank 304,890 (Top 7 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

XState Router. Add routes to your XState machine.

xstate-router

XState Router. Add routes to your XState machine and maintain it in sync with the actual route.

Use

Install the library with npm i xstate-router.

If you don't have XState installed, install it: npm i xstate

Try the live example here: https://codesandbox.io/s/rllly3pyxp.

The routerMachine function returns an interpreter:

import { routerMachine } from 'xstate-router'

const machineConfig = {
    initial: 'main',
    context: { myValue: 0 },
    states: {
        main: { meta: { path: '/' } },
        blog: { meta: { path: '/blog' } },
    },
}

const service = routerMachine({
    config: machineConfig,
    options,
    initialContext,
})

// The state changes on a route change and the route changes on a state change.
service.onTransition(state => console.log(state.value))

// The context is enhanced with router properties.
service.onChange(ctx => console.log(ctx))
/* Context
    {
        myValue: 0,
        // Router properties:
        match,
        location,
        history,
    }
*/

Use with React Hooks

import { useRouterMachine } from 'xstate-router'

const config = {
  initial: 'home',
  states: {
    home: { meta: { path: '/' }, on: { NEXT: 'about' } },
    about: { meta: { path: '/about' }, on: { NEXT: 'dashboard' } },
    dashboard: {
      meta: { path: '/dashboard' },
      initial: 'login',
      on: { NEXT: 'home' },
      states: {
        loggedIn: {
          initial: 'main',
          states: {
            main: { meta: { path: '/dashboard/main' } },
            data: { meta: { path: '/dashboard/data' } }
          }
        },
        login: {
          meta: { path: '/dashboard/login' },
          on: { LoggedIn: 'loggedIn' }
        }
      }
    }
  }
}

function App() {
    const service = useRouterMachine({ config })

    return <div>{service.state.value}</div>
}

Enhanced context

  1. match: Tells you whether the route in the location matches the current state's path. If it matches it contains an object holding properties for each route parameter's value if the path was parameterized. Examples: null (not matching), {} (no parameters), { param1: 4711 }
  2. location: The current value of history.location
  3. history: routerMachine(...) accepts a history object as fourth parameter. If it is missing it defaults to createBrowserHistory() (from package 'history') and is published in the context.

if you translate to a state having a parameterized route then you have to ensure that context.match contains the values of those parameters. Otherwise the placeholder is shown in the route. Example:

  states: {
      list: { meta: { path: '/items' },
         on: {
            ShowDetails: {
                target: 'details',
                actions: assign((ctx, event) => ({
                                    ...ctx,
                                    match: { id: event.item }
                                }))
            }
         }
      }
      details: { meta: { path: '/items/:id/details'} }
  }

where the event trigger could look like this:

<button onClick={() => this.send('ShowDetails', { item: 817 })}>Show details...</button>

Paths

Paths could have parameters such as /items/:id/details and regular expressions, for more information please read this: https://github.com/pillarjs/path-to-regexp.

Router events

If a route changes then a parameterized event 'route-changed' is fired: e.g. { dueToStateTransition: "true", route: "/blog", service: /* the xstate interpreter */ }.

  1. If the route changes because a state is entered which has a route configured, then dueToStateTransition is true. If the route changes because the location was changed (either by the user in the browsers location bar or by a script changing history.location), then dueToStateTransition is false.
  2. route gives you the current route which causes the event
  3. service provides the xstate interpreter which can be used to send another event.

Placing an on: 'router-changed' event at a state can be used to avoid leaving the current state if the route changes. Think of a state which might show unsaved data and you want to ask the user 'Leave and loose unsaved data?'. If you decide to accept the new route anyway you have to resend the event:

  on: {
    'route-changed': {
      cond: (context, event) => event.dueToStateTransition === false
          && !event.processed,            // interfere only new events
      actions: (context, event) => {
        if (context.unsavedData) return;  // suppress current route change
        event.processed = true;           // mark event as processed
        event.service.send(event);        // resend the event to establish the origin route change
      }
    }
  },

More Repositories

1

use-machine

React Hook for using Statecharts powered by XState. use-machine.
TypeScript
225
star
2

figma-app-linux

Unofficial Figma desktop app rebuild for Linux users.
JavaScript
86
star
3

blocklify

Edit code with blocks (Blockly code importer).
JavaScript
63
star
4

xstate-react-router

XState connector to React Router.
TypeScript
22
star
5

use-router-machine

Router state-machine hook, powered by XState (DEPRECATED).
TypeScript
12
star
6

BBlocks.js

Build with Blocks, the SVG based GUI library.
JavaScript
9
star
7

BB-editor

Visual programming editor research project.
JavaScript
7
star
8

figma-community-plugins

A collection of trusted community plugins for Figma.
6
star
9

gameoflife-xstate-react

Game of Life implemented with Statecharts and React
JavaScript
6
star
10

cross-safe-eval

Node.js and browser 8 lines implementation of a safe eval :)
JavaScript
5
star
11

markdown-it-codesandbox-embed

markdown-it plugin for creating sandboxes on the fly for your code examples. Use it with VuePress or any markdown-it based project.
JavaScript
5
star
12

lisp-js

Lisp interpreter written for the Web
TypeScript
5
star
13

figma-plugin-manager

Unofficial desktop app for using Figma plugins inside the Figma desktop app
JavaScript
4
star
14

Startup-Colombia-Empresas

Lista de empresas que participan en Startup Colombia
JavaScript
4
star
15

react-antd-emotion-starter-typescript

React Ant Design and Emotion Starter - TypeScript
TypeScript
3
star
16

schemy

Schemy is a set of tools for developing fullstack apps and backoffices with React, Next.js and PostgreSQL.
3
star
17

easy-i18n-blockly

Easy hot translation of blockly blocks.
JavaScript
3
star
18

TSLox

TypeScript implementation of the Lox language from the Crafting Interpreters book.
TypeScript
2
star
19

Distributed-Identity-Protocol

Secure and flexible authentication protocol with cache for offline use
TypeScript
2
star
20

mind-control

Bringing mind-control to the web.
JavaScript
2
star
21

pullable-event-bus

An event bus where emitters can pull data from subscribers
TypeScript
1
star
22

jqm-angular-extension

Easy and simple way for integrate jquery mobile and angularjs
JavaScript
1
star
23

cloudant-helpers

Cloudant helpers for common tasks such as securely call the api avoiding 429 error
TypeScript
1
star
24

Solver.js

Solve problems made simple.
JavaScript
1
star
25

La-Web-es-el-futuro

Presentaciรณn con ejemplos de las tecnologias Web y su potencial
TypeScript
1
star
26

tribe-tech-test

Technical Test Full-Stack Engineering Tribe.
CSS
1
star
27

svelte-concepts-demo

Svelte demo for BogotaJS talk
HTML
1
star
28

carloslfu.github.io

Carlos Galarza's website. Made with NextJS, React, Styled System and love ;).
JavaScript
1
star
29

blockly-debug

blockly copy for debuging online, use gh-pages
JavaScript
1
star
30

BBlocksNext.js

Repo for experimenting with BBlocks.js implemented with cycle.js
JavaScript
1
star
31

smartest

Simple e2e tests and automated screenshoots using Puppeteer
TypeScript
1
star
32

Universal-Web-Loader

A bundler and package manager that runs in your browser and can import npm modules (Work in progress ...)
JavaScript
1
star