usestatetransition

Other flavor of a state machine hook

Usage no npm install needed!

<script type="module">
  import usestatetransition from 'https://cdn.skypack.dev/usestatetransition';
</script>

README

useStateTransition

If you look for a classic state machine, check cassiozen/useStateMachine.

Problem

One of my project is an app that can open various editors. Each editor can have different implementation, but needs to follow the same lifecycle. I wanted to provide a neat small hook that would handle it, so specific editors don't have too keep too much knowledge about the host app.

While doing it turned out I need some sort of state machine. The difference was that I need it to be focused more on transition between specific states.

Other nice projects implementing state machine hook were following enter/leave version of the pattern, that was focused on the state, rather than transition.

Example

Check the tests example.

const { state, dispatch } = useStateTransition<EditorState>({
    initial: EditorState.INIT,
    flows: [
      {
        from: EditorState.INIT,
        to: EditorState.READY,
        on: (_, setState) => {
          setState(scenario === "new" ? EditorState.NEW : EditorState.LOAD);
        },
      },
      {
        from: [EditorState.NEW, EditorState.LOAD],
        to: EditorState.OPEN,
      },
    ],
  });

API

const { state, dispatch, error } = useStateTransition<StateType>(options)

state

Current state of provided StateType. The first value comes from initial field in options.

dispatch

type Dispatch = (requestedState: StateType, data?: unknown) => void;

You use it to trigger the transition. Transition to the same state won't trigger any updates. If the request create unknown transition error will be populated.

Conditional dispatch

You can pass a function to dispatch to decide which state you dispatch to based on the current state. It's useful when you dispatch comes from useCallback which would cache the initial state


dispatchFn((currentState, data) => {
  if (currentState = 1) {
    return {
      to: 2,
      data // you can decide to pass the data
    }
  }
  return {
      to: 3
      // or to filter out the data
  }
}

error

Display the latest error. At the moment it reports only about unknown transitions.

options

You need to define the initialValue of the state and the flows.

{
    initialValue: StateType,
    flows: Flow[]
}

Flow

{
    from: StateType | StateType[],
    to: State | StateType[],
    on?: (requestedState: StateType, setState: (state: StateType) => void, data?: unknown) => void;
}
  • from defines the state you want to transition from; you can specify one or many states.
  • to defines the state you want to transition to; you can specify oen or many states.
  • on (optional)
    • if absent the state machine will just allow transition
    • if present it works like a guard, in the end you can specify which state you want to set. It won't trigger another guard or test, it will just update the sate.
    • you have access to data passed, so you can update your other hooks.
    • it happens in useEffect

License

MIT