Function useMachine

  • Uses a state machine with the constructor.

    Each time the state machine transitions to a new state, React.setState is called internally, triggering a re-render of the component.

    The state machine constructor is executed only once per hook. It is idempotent unless it depends on external mutable values within the constructor.

    Type Parameters

    • D

      The type of state machine definition.

    Parameters

    Returns [state: State<D>, send: Send<D>]

    An array with two elements:

    • The first element is the current state of the state machine.
    • The second element is a function that sends an event to the state machine.
    import { useMachine, createMachine } from "use-machine-ts"

    function machine() {
    return createMachine({
    // definition
    {
    initial: "inactive",
    states: {
    inactive: {
    on: { TOGGLE: "active" },
    effect: "onInactive",
    },
    active: {
    on: { TOGGLE: "inactive" },
    effect: "onActive",
    },
    },
    },
    // configuration
    {
    effects: {
    onActive: () => {
    console.log("Just activated!")
    },
    onInactive: () => {
    console.log("Just deactivated!")
    },
    },
    },
    })
    }

    function ToggleButton(props: {}) {
    const [state, send] = useMachine(machine)

    return (
    <button onClick={() => send("TOGGLE")} type="button">
    Now: {state.value}
    </button>
    )
    }
  • Uses a state machine with the constructor and props.

    Each time the state machine transitions to a new state, React.setState is called internally, triggering a re-render of the component.

    The state machine constructor is executed only once per hook. It is idempotent unless it depends on external mutable values within the constructor.

    The props passed to the state machine constructor are different from the props of a React component; they are represented as a function. When this function is executed, it returns a reference to the props passed to the hook. This mechanism is implemented using React.useRef, ensuring that it always returns a reference to the latest props.

    Type Parameters

    • D

      The type of state machine definition.

    • P

      The type of props for the state machine constructor.

    Parameters

    • machine: ((props: (() => P)) => Machine<D>)

      The state machine constructor.

    • props: P

      The props for the state machine constructor.

    Returns [state: State<D>, send: Send<D>]

    An array with two elements:

    • The first element is the current state of the state machine.
    • The second element is a function that sends an event to the state machine.
    import { useMachine, createMachine } from "use-machine-ts"

    function machine(props: () => { onToggle }) {
    return createMachine({
    // definition
    {
    initial: "inactive",
    states: {
    inactive: {
    on: { TOGGLE: "active" },
    effect: "onInactive",
    },
    active: {
    on: { TOGGLE: "inactive" },
    effect: "onActive",
    },
    },
    },
    // configuration
    {
    effects: {
    onActive: () => {
    const { onToggle } = props()
    onToggle("active")
    },
    onInactive: () => {
    const { onToggle } = props()
    onToggle("inactive")
    },
    },
    },
    })
    }

    function ToggleButton(props: { onToggle: (value: "active" | "inactive") => void }) {
    const [state, send] = useMachine(machine, props)

    return (
    <button onClick={() => send("TOGGLE")} type="button">
    Now: {state.value}
    </button>
    )
    }
  • Uses a state machine with the pre-created instance.

    Each time the state machine transitions to a new state, React.setState is called internally, triggering a re-render of the component.

    We can use a pre-created state machine instance with the hook. It is idempotent unless it depends on external mutable values within the effect. In most cases, it is better to define the state machine using the constructor instead.

    To enable tree shaking, you can indicate to the bundler that this function has no side effects by using the @__PURE__ or #__PURE__ annotation as needed.

    Type Parameters

    • D

      The type of state machine definition.

    Parameters

    • machine: Machine<D>

      The state machine instance.

    Returns [state: State<D>, send: Send<D>]

    An array with two elements:

    • The first element is the current state of the state machine.
    • The second element is a function that sends an event to the state machine.
    import { useMachine, createMachine } from "use-machine-ts"

    const machine = createMachine({
    // definition
    {
    initial: "inactive",
    states: {
    inactive: {
    on: { TOGGLE: "active" },
    effect: "onInactive",
    },
    active: {
    on: { TOGGLE: "inactive" },
    effect: "onActive",
    },
    },
    },
    // configuration
    {
    effects: {
    onActive: () => {
    console.log("Just activated!")
    },
    onInactive: () => {
    console.log("Just deactivated!")
    },
    },
    },
    })

    function ToggleButton(props: {}) {
    const [state, send] = useMachine(machine)

    return (
    <button onClick={() => send("TOGGLE")} type="button">
    Now: {state.value}
    </button>
    )
    }
  • Define a state machine and uses it.

    Each time the state machine transitions to a new state, React.setState is called internally, triggering a re-render of the component.

    This approach is useful when you want to quickly define and use a simple state machine on the spot. For complex definitions, it is usually better to write them in a separate file and import it. However, if the definition does not impair readability, keeping it within the component can actually make it more readable.

    Type Parameters

    • D extends {
          $schema?: Schema<D, ["$schema"], "$schema" extends keyof D
              ? D[keyof D & "$schema"] extends undefined
                  ? undefined
                  : D[keyof D & "$schema"]
              : undefined, "strict" extends keyof ("$schema" extends keyof D
                  ? D[keyof (...) & "$schema"] extends undefined
                      ? undefined
                      : D[keyof (...) & "$schema"]
                  : undefined)
              ? ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "strict"] extends undefined
                  ? undefined
                  : ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "strict"]
              : undefined, "events" extends keyof ("$schema" extends keyof D
                  ? D[keyof (...) & "$schema"] extends undefined
                      ? undefined
                      : D[keyof (...) & "$schema"]
                  : undefined)
              ? ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "events"] extends undefined
                  ? undefined
                  : ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "events"]
              : undefined, "context" extends keyof ("$schema" extends keyof D
                  ? D[keyof (...) & "$schema"] extends undefined
                      ? undefined
                      : D[keyof (...) & "$schema"]
                  : undefined)
              ? ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "context"] extends undefined
                  ? undefined
                  : ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "context"]
              : undefined>;
          initial: IsPlainObject<"states" extends keyof D
                  ? D[keyof D & "states"] extends undefined
                      ? undefined
                      : D[keyof D & "states"]
                  : undefined> extends false
              ? "Error: States must be a plain object."
              : [keyof ("states" extends keyof D
                      ? D[keyof (...) & "states"] extends undefined
                          ? undefined
                          : D[keyof (...) & "states"]
                      : undefined)] extends [never]
                  ? "Error: No states defined."
                  : IsStringLiteral<keyof ("states" extends keyof D
                          ? D[(...) & (...)] extends undefined
                              ? undefined
                              : D[(...) & (...)]
                          : undefined)> extends false
                      ? "Error: States have no literal string value."
                      : keyof ("states" extends keyof D
                          ? D[keyof (...) & "states"] extends undefined
                              ? undefined
                              : D[keyof (...) & "states"]
                          : undefined);
          on?: On<D, ["on"], never>;
          states: IsPlainObject<"states" extends keyof D
                  ? D[keyof D & "states"] extends undefined
                      ? undefined
                      : D[keyof D & "states"]
                  : undefined> extends false
              ? "Error: States must be a plain object."
              : [keyof ("states" extends keyof D
                      ? D[keyof (...) & "states"] extends undefined
                          ? undefined
                          : D[keyof (...) & "states"]
                      : undefined)] extends [never]
                  ? {
                      [NEVER]?: undefined;
                  }
                  : IsStringLiteral<keyof ("states" extends keyof D
                          ? D[(...) & (...)] extends undefined
                              ? undefined
                              : D[(...) & (...)]
                          : undefined)> extends false
                      ? "Error: State values must be literal strings."
                      : {
                          readonly [V in string | number | symbol]: V extends ReservedKeyword
                              ? `Error: State value '${V<V>}' is reserved.`
                              : Definition.State<D, ["states", V], never, never>
                      };
      } & ({
          context: Context<D>;
      } | {
          context?: Context<D>;
      })

      The type of state machine definition.

    Parameters

    Returns [state: State<D>, send: Send<D>]

    An array with two elements:

    • The first element is the current state of the state machine.
    • The second element is a function that sends an event to the state machine.
    import { useMachine } from "use-machine-ts"

    function ToggleButton(props: {}) {
    const [state, send] = useMachine(
    // definition
    {
    initial: "inactive",
    states: {
    inactive: {
    on: { TOGGLE: "active" },
    },
    active: {
    on: { TOGGLE: "inactive" },
    },
    },
    },
    )

    return (
    <button onClick={() => send("TOGGLE")} type="button">
    Now: {state.value}
    </button>
    )
    }
  • Define a state machine and uses it.

    Each time the state machine transitions to a new state, React.setState is called internally, triggering a re-render of the component.

    This approach is useful when you want to quickly define and use a simple state machine on the spot. For complex definitions, it is usually better to write them in a separate file and import it. However, if the definition does not impair readability, keeping it within the component can actually make it more readable.

    Type Parameters

    • D extends {
          $schema?: Schema<D, ["$schema"], "$schema" extends keyof D
              ? D[keyof D & "$schema"] extends undefined
                  ? undefined
                  : D[keyof D & "$schema"]
              : undefined, "strict" extends keyof ("$schema" extends keyof D
                  ? D[keyof (...) & "$schema"] extends undefined
                      ? undefined
                      : D[keyof (...) & "$schema"]
                  : undefined)
              ? ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "strict"] extends undefined
                  ? undefined
                  : ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "strict"]
              : undefined, "events" extends keyof ("$schema" extends keyof D
                  ? D[keyof (...) & "$schema"] extends undefined
                      ? undefined
                      : D[keyof (...) & "$schema"]
                  : undefined)
              ? ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "events"] extends undefined
                  ? undefined
                  : ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "events"]
              : undefined, "context" extends keyof ("$schema" extends keyof D
                  ? D[keyof (...) & "$schema"] extends undefined
                      ? undefined
                      : D[keyof (...) & "$schema"]
                  : undefined)
              ? ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "context"] extends undefined
                  ? undefined
                  : ("$schema" extends keyof D
                      ? D[(...) & (...)] extends undefined
                          ? undefined
                          : D[(...) & (...)]
                      : undefined)[keyof ("$schema" extends keyof (...)
                      ? (...) extends (...)
                          ? (...)
                          : (...)
                      : undefined) & "context"]
              : undefined>;
          initial: IsPlainObject<"states" extends keyof D
                  ? D[keyof D & "states"] extends undefined
                      ? undefined
                      : D[keyof D & "states"]
                  : undefined> extends false
              ? "Error: States must be a plain object."
              : [keyof ("states" extends keyof D
                      ? D[keyof (...) & "states"] extends undefined
                          ? undefined
                          : D[keyof (...) & "states"]
                      : undefined)] extends [never]
                  ? "Error: No states defined."
                  : IsStringLiteral<keyof ("states" extends keyof D
                          ? D[(...) & (...)] extends undefined
                              ? undefined
                              : D[(...) & (...)]
                          : undefined)> extends false
                      ? "Error: States have no literal string value."
                      : keyof ("states" extends keyof D
                          ? D[keyof (...) & "states"] extends undefined
                              ? undefined
                              : D[keyof (...) & "states"]
                          : undefined);
          on?: On<D, ["on"], G>;
          states: IsPlainObject<"states" extends keyof D
                  ? D[keyof D & "states"] extends undefined
                      ? undefined
                      : D[keyof D & "states"]
                  : undefined> extends false
              ? "Error: States must be a plain object."
              : [keyof ("states" extends keyof D
                      ? D[keyof (...) & "states"] extends undefined
                          ? undefined
                          : D[keyof (...) & "states"]
                      : undefined)] extends [never]
                  ? {
                      [NEVER]?: undefined;
                  }
                  : IsStringLiteral<keyof ("states" extends keyof D
                          ? D[(...) & (...)] extends undefined
                              ? undefined
                              : D[(...) & (...)]
                          : undefined)> extends false
                      ? "Error: State values must be literal strings."
                      : {
                          readonly [V in string | number | symbol]: V extends ReservedKeyword
                              ? `Error: State value '${V<V>}' is reserved.`
                              : Definition.State<D, ["states", V], G, E>
                      };
      } & ({
          context: Context<D>;
      } | {
          context?: Context<D>;
      })

      The type of state machine definition.

    • const G extends string

      The type of guards for state machine functions.

    • const E extends string

      The type of effects for state machine functions.

    Parameters

    Returns [state: State<D>, send: Send<D>]

    An array with two elements:

    • The first element is the current state of the state machine.
    • The second element is a function that sends an event to the state machine.
    import { useMachine } from "use-machine-ts"

    function ToggleButton(props: {}) {
    const [state, send] = useMachine(
    // definition
    {
    initial: "inactive",
    states: {
    inactive: {
    on: { TOGGLE: "active" },
    effect: "onInactive",
    },
    active: {
    on: { TOGGLE: "inactive" },
    effect: "onActive",
    },
    },
    },
    // configuration
    {
    effects: {
    onActive: () => {
    console.log("Just activated!")
    },
    onInactive: () => {
    console.log("Just deactivated!")
    },
    },
    },
    )

    return (
    <button onClick={() => send("TOGGLE")} type="button">
    Now: {state.value}
    </button>
    )
    }