Xstate: [Feature] - I Need examples of complicated state machines

Created on 16 Dec 2019  路  7Comments  路  Source: davidkpiano/xstate

Description

I'm working on a builder function for xstate. ( dirty work is done on https://github.com/iliasbhal/xstate-builder (~10kb) ). I really want to make a PR as soon as possible on xstate, but I need to create a bunch of "stress tests" before embarrassing myself on the PR.

In order to do so, I'm asking you ( if you accept the mission ) to respond on this thread with simple to complicated xstate machine configurations objects. ( Or if you know where I can find a bunch of xstate configurations 馃 )

I will:

  • recreate those machines using the builder.
  • add tests to ensure the builder works correctly against a wide variety of machine configurations.
  • improve/add features/handy methods to the builder.

Why am I working on a builder for xstate?

We have superpowers, we can code. But the Configuration Object ( while it's very efficient for xstate internal use or for debugging purposes ), it's restricting our minds and superpowers, we can do a lot more than configuring the object.

Some Benefits:

  • Autocomplete and improved API discovery 馃憣.
  • Type checking is done at the function level.
  • Use any package in npm to help you configure your machine.
  • Ability to quickly have a clear view of all the different states of the machine.
  • Write the same machine with fewer lines of code.
  • Increase Maintainability: Easier to read and understand ( because of the fluent API ).
  • Ability to organize the code in a way that makes the more sense to you.
  • Integrates with all the js/ts tools you already have
  • It doesn't interfere at any level with xstate since it only creates the config object xstate will consume.

Simple Example (but you can do much much more):

// this example is a unidirectional state loop.
const xStateConfig = Machine.Builder(state => {
  const node1 = state.atomic('node-1');
  const node2 = state.atomic('node-2');
  const node3 = state.atomic('node-3');

  [node1, node2, node3].forEach((node, index, nodes) => {
    const nextNode = nodes[index + 1] ?? nodes[0]
    node.on('NEXT').target(nextNode)
  })
})
// Outputs:
{
  initial: 'node-1',
  states: {
    'node-1': {
      type: 'atomic',
      on: {
        NEXT: 'node-2',
      },
    },
    'node-2': {
      type: 'atomic',
      on: {
        NEXT: 'node-3',
      },
    },
    'node-3': {
      type: 'atomic',
      on: {
        NEXT: 'node-1',
      },
    },
  },
}

Make the world a better place

I have a passion for helping other developers like you to achieve more by doing less. Please help me in my mission by sharing examples of xstate machine configurations 馃檹.

Note:

I really want to thank you @davidkpiano for your work on xstate. I knew about state machines but you gave me another perspective on them. I want to see state machines everywhere now 馃ぃ . Thank you for making the process of software development way easier to code, collaborate, visualize, test, understand, onboard, maintain. (actually, everything is easier with xstate 馃檭 馃憤)

Most helpful comment

@CodingDive I'm working on this actually... (don't share this) it's going to be a new minimal package called XActor, which I've already started on.

The goal is for you to define systems of actors in a very simple way, and be able to fully log, trace, visualize them, etc.

import { createSystem } from 'xactor';

const system = createSystem('example');

const actor = system.spawn(someBehavior);

actor.send('SOME_EVENT');

All 7 comments

I also need you opinions on what nifty methods you would like me to add :)

Very cool. The configuration object is meant to be low-level (but at an abstraction that still makes it acceptable to code manually), so I'm excited to see higher-level APIs on top of this!

The project you are proposing sounds incredible. 馃槏

Are you also planning to build abstraction above actor communication? I have to think about it some more but I could see an API where one declaratively defines two actors and the relationship between them. This could maybe allow us to define the event of an actor and how the event is send by another actor, inside the same API call(s) using the builder. This could reduce the number of files one needs to look at and put a greater emphasis on actor communication when writing machines. Do you think an API for this is feasible?

@iliasbhal feel free to use https://codesandbox.io/s/ecstatic-leavitt-9codx which uses a lot of XState functionality. Tons of conditional state transitions, actors, parallel states. and deeply nested state nodes. I would love to see how this code looks like with the first iteration of your builder. You can also use any of the other state machines in the blog post series I wrote https://dev.to/codingdive/introducing-state-machine-advent-24-bite-sized-blog-posts-about-state-machines-and-statecharts-2ce0 but none of them are as complex as the sandbox linked above from day 23.

@CodingDive I'm working on this actually... (don't share this) it's going to be a new minimal package called XActor, which I've already started on.

The goal is for you to define systems of actors in a very simple way, and be able to fully log, trace, visualize them, etc.

import { createSystem } from 'xactor';

const system = createSystem('example');

const actor = system.spawn(someBehavior);

actor.send('SOME_EVENT');

@davidkpiano could you share a little bit more about what kind of problems is this API suppose to solve? Will it be a part ofc XState? Something complementary to it? Or maybe something entirely different?

@CodingDive, thanks for all those examples 馃憤 I'll add those to the test cases :).
The more I implement different state machines, the more I "discover" patterns involved around configuring a state machine using the builder. This already led me to implement some nice handy methods that ease the process of building a state machine even more. Thanks again!


Are you also planning to build abstraction above actor communication?

I am! At the moment, I have created an event-bus that let you send events to any machine registered at an address within the same process or browser window.
But this is really just a proof of concept at this stage. What I really want is to use any channel you want not just a hardcoded event bus.

I would be interested to look into xactor once it's open-sourced ( if it's going to be part of xstate ) so that I can start integrate it into the builder. I'd be more than happy to rely on that one or another package for the actor system implementation 馃憤

Closing this for now - you can find many examples of state machines here: https://gist.github.com/search?q=xstate

Was this page helpful?
0 / 5 - 0 ratings