xstate README

The project's README from github.com/statelyai/xstate. As one markdown file: README.md.


XState logotype
Actor-based state management & orchestration for complex app logic. → Documentation

XState is a state management and orchestration solution for JavaScript and TypeScript apps. It has zero dependencies, and is useful for frontend and backend application logic.

It uses event-driven programming, state machines, statecharts, and the actor model to handle complex logic in predictable, robust, and visual ways. XState provides a powerful and flexible way to manage application and workflow state by allowing developers to model logic as actors and state machines.

✨ Create state machines visually in Stately Studio → state.new


📖 Read the documentation

➡️ Create state machines with the Stately Editor

🖥 Download our VS Code extension

📑 Inspired by the SCXML specification

💬 Chat on the Stately Discord Community

✍️ Browse through the many XState examples

Which package should I use?

Pick based on what you need:

They work great together, but you don't need one to use the other.

Sponsors

Special thanks to the sponsors who support this open-source project:

Templates

Get started by forking one of these templates on CodeSandbox:

Template

🤖 XState Template (CodeSandbox)

Open in StackBlitz

  • XState v5
  • TypeScript
  • No framework

⚛️ XState + React Template (CodeSandbox)

Open in StackBlitz

  • React
  • XState v5
  • TypeScript

💚 XState + Vue Template (CodeSandbox)

Open in StackBlitz

  • Vue
  • XState v5
  • TypeScript

🧡 XState + Svelte Template (CodeSandbox)

Open in StackBlitz

Super quick start

npm install xstate
import { createMachine, createActor, assign } from 'xstate';

// State machine
const toggleMachine = createMachine({
  id: 'toggle',
  initial: 'inactive',
  context: {
    count: 0
  },
  states: {
    inactive: {
      on: {
        TOGGLE: { target: 'active' }
      }
    },
    active: {
      entry: assign({ count: ({ context }) => context.count + 1 }),
      on: {
        TOGGLE: { target: 'inactive' }
      }
    }
  }
});

// Actor (instance of the machine logic, like a store)
const toggleActor = createActor(toggleMachine);
toggleActor.subscribe((state) => console.log(state.value, state.context));
toggleActor.start();
// => logs 'inactive', { count: 0 }

toggleActor.send({ type: 'TOGGLE' });
// => logs 'active', { count: 1 }

toggleActor.send({ type: 'TOGGLE' });
// => logs 'inactive', { count: 1 }

@xstate/store: simple state management

Not every app needs all the features of state machines and statecharts. @xstate/store is a separate, extremely small event-based store with first-class TypeScript inference; similar to Redux or Zustand, but with less boilerplate.

Use it on its own, or graduate to full XState machines when your logic gets more complex.

npm install @xstate/store
import { createStore } from '@xstate/store';

const donutStore = createStore({
  context: {
    donuts: 0,
    favoriteFlavor: 'chocolate'
  },
  on: {
    addDonut: (context) => ({ ...context, donuts: context.donuts + 1 }),
    changeFlavor: (context, event: { flavor: string }) => ({
      ...context,
      favoriteFlavor: event.flavor
    }),
    eatAllDonuts: (context) => ({ ...context, donuts: 0 })
  }
});

donutStore.subscribe((snapshot) => {
  console.log(snapshot.context);
});

donutStore.send({ type: 'addDonut' });
// => { donuts: 1, favoriteFlavor: 'chocolate' }

donutStore.send({ type: 'changeFlavor', flavor: 'strawberry' });
// => { donuts: 1, favoriteFlavor: 'strawberry' }

📖 See the @xstate/store README for React/Solid bindings, selectors, and more.


Stately Studio

XState Viz

state.new

Why?

Statecharts are a formalism for modeling stateful, reactive systems. This is useful for declaratively describing the behavior of your application, from the individual components to the overall application logic.

Read 📽 the slides (🎥 video) or check out these resources for learning about the importance of finite state machines and statecharts in user interfaces:

Packages

Package Description
🤖 xstate Core finite state machine and statecharts library + interpreter, including graph traversal and model-based testing utilities
🏪 @xstate/store Simple event-based state management (<1kb) — standalone, works with or without xstate
⚛️ @xstate/react React hooks and utilities for using XState in React applications
💚 @xstate/vue Vue composition functions and utilities for using XState in Vue applications
🎷 @xstate/svelte Svelte utilities for using XState in Svelte applications
🥏 @xstate/solid Solid hooks and utilities for using XState in Solid applications
🔍 @statelyai/inspect Inspection utilities for XState

Finite State Machines

CodeStatechart
import { createMachine, createActor } from 'xstate';

const lightMachine = createMachine({
  id: 'light',
  initial: 'green',
  states: {
    green: {
      on: {
        TIMER: 'yellow'
      }
    },
    yellow: {
      on: {
        TIMER: 'red'
      }
    },
    red: {
      on: {
        TIMER: 'green'
      }
    }
  }
});

const actor = createActor(lightMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs 'green'

actor.send({ type: 'TIMER' });
// logs 'yellow'
Finite states
Open in Stately Studio

Hierarchical (Nested) State Machines

CodeStatechart
import { createMachine, createActor } from 'xstate';

const pedestrianStates = {
  initial: 'walk',
  states: {
    walk: {
      on: {
        PED_TIMER: 'wait'
      }
    },
    wait: {
      on: {
        PED_TIMER: 'stop'
      }
    },
    stop: {}
  }
};

const lightMachine = createMachine({
  id: 'light',
  initial: 'green',
  states: {
    green: {
      on: {
        TIMER: 'yellow'
      }
    },
    yellow: {
      on: {
        TIMER: 'red'
      }
    },
    red: {
      on: {
        TIMER: 'green'
      },
      ...pedestrianStates
    }
  }
});

const actor = createActor(lightMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs 'green'

actor.send({ type: 'TIMER' });
// logs 'yellow'

actor.send({ type: 'TIMER' });
// logs { red: 'walk' }

actor.send({ type: 'PED_TIMER' });
// logs { red: 'wait' }
Hierarchical states
Open in Stately Studio

Parallel State Machines

CodeStatechart
import { createMachine, createActor } from 'xstate';

const wordMachine = createMachine({
  id: 'word',
  type: 'parallel',
  states: {
    bold: {
      initial: 'off',
      states: {
        on: {
          on: { TOGGLE_BOLD: 'off' }
        },
        off: {
          on: { TOGGLE_BOLD: 'on' }
        }
      }
    },
    underline: {
      initial: 'off',
      states: {
        on: {
          on: { TOGGLE_UNDERLINE: 'off' }
        },
        off: {
          on: { TOGGLE_UNDERLINE: 'on' }
        }
      }
    },
    italics: {
      initial: 'off',
      states: {
        on: {
          on: { TOGGLE_ITALICS: 'off' }
        },
        off: {
          on: { TOGGLE_ITALICS: 'on' }
        }
      }
    },
    list: {
      initial: 'none',
      states: {
        none: {
          on: {
            BULLETS: 'bullets',
            NUMBERS: 'numbers'
          }
        },
        bullets: {
          on: {
            NONE: 'none',
            NUMBERS: 'numbers'
          }
        },
        numbers: {
          on: {
            BULLETS: 'bullets',
            NONE: 'none'
          }
        }
      }
    }
  }
});

const actor = createActor(wordMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs {
//   bold: 'off',
//   italics: 'off',
//   underline: 'off',
//   list: 'none'
// }

actor.send({ type: 'TOGGLE_BOLD' });
// logs {
//   bold: 'on',
//   italics: 'off',
//   underline: 'off',
//   list: 'none'
// }

actor.send({ type: 'TOGGLE_ITALICS' });
// logs {
//   bold: 'on',
//   italics: 'on',
//   underline: 'off',
//   list: 'none'
// }
Parallel states
Open in Stately Studio

History States

CodeStatechart
import { createMachine, createActor } from 'xstate';

const paymentMachine = createMachine({
  id: 'payment',
  initial: 'method',
  states: {
    method: {
      initial: 'cash',
      states: {
        cash: {
          on: {
            SWITCH_CHECK: 'check'
          }
        },
        check: {
          on: {
            SWITCH_CASH: 'cash'
          }
        },
        hist: { type: 'history' }
      },
      on: { NEXT: 'review' }
    },
    review: {
      on: { PREVIOUS: 'method.hist' }
    }
  }
});

const actor = createActor(paymentMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs {
//   value: { method: 'cash' },
// }

actor.send({ type: 'SWITCH_CHECK' });
// logs {
//   value: { method: 'check' },
// }

actor.send({ type: 'NEXT' });
// logs {
//   value: 'review',
// }

actor.send({ type: 'PREVIOUS' });
// logs {
//   value: { method: 'check' },
// }
History state
Open in Stately Studio

SemVer Policy

We understand the importance of the public contract and do not intend to release any breaking changes to the runtime API in a minor or patch release. We consider this with any changes we make to the XState libraries and aim to minimize their effects on existing users.

Breaking changes

XState executes much of the user logic itself. Therefore, almost any change to its behavior might be considered a breaking change. We recognize this as a potential problem but believe that treating every change as a breaking change is not practical. We do our best to implement new features thoughtfully to enable our users to implement their logic in a better, safer way.

Any change could affect how existing XState machines behave if those machines are using particular configurations. We do not introduce behavior changes on a whim and aim to avoid making changes that affect most existing machines. But we reserve the right to make some behavior changes in minor releases. Our best judgment of the situation will always dictate such changes. Please always read our release notes before deciding to upgrade.

TypeScript changes

We also reserve a similar right to adjust declared TypeScript definitions or drop support for older versions of TypeScript in a minor release. The TypeScript language itself evolves quickly and often introduces breaking changes in its minor releases. Our team is also continuously learning how to leverage TypeScript more effectively - and the types improve as a result.

For these reasons, it is impractical for our team to be bound by decisions taken when an older version of TypeScript was its latest version or when we didn’t know how to declare our types in a better way. We won’t introduce declaration changes often - but we are more likely to do so than with runtime changes.

Packages

Most of the packages in the XState family declare a peer dependency on XState itself. We’ll be cautious about maintaining compatibility with already-released packages when releasing a new version of XState, but each release of packages depending on XState will always adjust the declared peer dependency range to include the latest version of XState. For example, you should always be able to update xstate without @xstate/react. But when you update @xstate/react, we highly recommend updating xstate too.

xstate (statelyai/xstate)

Searching Database…

30.3K ·GitHub
这是什么?XState 是一个面向 JavaScript 和 TypeScript 应用的状态管理与编排方案。它把复杂的应用逻辑建模为状态机、状态图(statechart)和 Actor,让程序行为保持可预测、稳健,并且可视化。
它是添加到我项目里的库,还是一个独立的工具?是一系列 npm 库:核心的 xstate 包是一个带解释器的有限状态机和状态图(statechart)库,还有配套包(如 @xstate/store)以及框架绑定(如 @xstate/react)。
我怎么把它跑起来?从 npm 安装 xstate 包,或者 fork 一个现成的 CodeSandbox 模板——有纯 TypeScript、React、Vue 和 Svelte 版本——马上就能在浏览器里试。
它能配合 React 和 Vue 用吗?可以——核心库与框架无关,零依赖,前端和后端都能运行;如果你需要,还有 React、Vue 和 Svelte 的官方集成。
升级到新版本时有什么要注意的?由于 XState 会执行你应用中的大量逻辑,次版本发布也可能包含行为变化,TypeScript 类型定义也可能在次版本中调整——升级前务必阅读发布说明。
@xstate/store 是什么?什么时候我会选它而不是完整的 XState?它是一个独立的、极其精简的基于事件的 store,TypeScript 类型推断是一等公民——类似 Redux 或 Zustand,但样板代码更少。简单的状态管理可以从它入手,等逻辑变复杂了再升级到完整的状态机。
Stately Studio 是什么?一个用于创建、编辑和协作开发状态机的可视化编辑器。它可以导出 XState v5,自动生成测试路径和文档,能部署到 Stately Sky,还内置 AI 辅助的状态机生成功能。
为什么要把应用逻辑建模成状态图(statechart),而不是用普通的状态管理?状态图是一种为有状态、响应式系统建模的形式化方法。它以声明式的方式描述应用行为——从单个组件到整体应用逻辑——让复杂的流程保持可预测,并且容易可视化。
我能在编辑器里可视化地编辑状态机吗?可以——有一个 XState 的 VS Code 扩展;如果需要带协作和自动生成功能的完整可视化编辑,可以在 Stately Studio 中打开状态机。
What are similar projects?Recoil, jotai, formily, shaders, akka-core, xyflow, mitosis, blobatar
Creator
statelyai
Size
273 MB
Stars
30.3K
Age
11y
Commits · 90 Days