0.2.0 • Published 3 months ago

@xstate/solid v0.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

@xstate/solid

The @xstate/solid package contains utilities for using XState with SolidJS.

[toc]

Quick Start

  1. Install xstate and @xstate/solid:
npm i xstate @xstate/solid
  1. Import the useActor hook:
import { useActor } from '@xstate/solid';
import { createMachine } from 'xstate';

const toggleMachine = createMachine({
  id: 'toggle',
  initial: 'inactive',
  states: {
    inactive: {
      on: { TOGGLE: 'active' }
    },
    active: {
      on: { TOGGLE: 'inactive' }
    }
  }
});

export const Toggler = () => {
  const [snapshot, send] = useActor(toggleMachine);

  return (
    <button onclick={() => send({ type: 'TOGGLE' })}>
      {snapshot.value === 'inactive'
        ? 'Click to activate'
        : 'Active! Click to deactivate'}
    </button>
  );
};

API

useActor(logic, options?)

A SolidJS hook that interprets the given logic and starts an actor that runs for the lifetime of the component.

Arguments

  • logic

    // existing machine
    const [snapshot, send] = useMachine(machine);

Returns a tuple of [snapshot, send, actorRef]:

  • snapshot - Represents the current snapshot of the logic. This is a read-only value that is tracked by SolidJS for granular reactivity.
  • send - A function that sends events to the running service.
  • actorRef - The created service.

fromActorRef(actorRf)

A SolidJS hook that subscribes to emitted changes from an existing actor.

Arguments

  • actorRef - an actor object that contains .send(...) and .subscribe(...) methods. Allows SolidJS Signal (or function) to dynamically specify an actor.
const snapshot = fromActorRef(someSpawnedActor);

useActorRef(logic, options?)

A SolidJS hook that returns the actorRef created from the logic with the options, if specified. It starts the actor and runs it for the lifetime of the component. This is similar to useActor.

createService returns a static reference (to just the interpreted logic) which will not rerender when its snapshot changes.

Arguments

import { useActorRef } from '@xstate/solid';
import { someMachine } from '../path/to/someMachine';

const App = () => {
  const actorRef = useActorRef(someMachine);

  // ...
};

With options:

// ...

const App = () => {
  const service = useActorRef(someMachine, {
    input: {
      /* ... */
    }
  });

  // ...
};

Matching States

When using hierarchical and parallel machines, the state values will be objects, not strings. In this case, it is best to use state.matches(...).

The SolidJS Switch and Match Components are ideal for this use case:

const Loader = () => {
  const [snapshot, send] = useActor(/* ... */);

  return (
    <div>
      <Switch fallback={null}>
        <Match when={snapshot.matches('idle')}>
          <Loader.Idle />
        </Match>
        <Match when={snapshot.matches({ loading: 'user' })}>
          <Loader.LoadingUser />
        </Match>
        <Match when={snapshot.matches({ loading: 'friends' })}>
          <Loader.LoadingFriends />
        </Match>
      </Switch>
    </div>
  );
};

Persisted and Rehydrated State

You can persist and rehydrate state with useActor(...) via options.snapshot:

// ...

// Get the persisted state config object from somewhere, e.g. localStorage
const persistedSnapshot = JSON.parse(localStorage.getItem('some-persisted-state-key')) || someMachine.initialState;

const App = () => {
  const [snapshot, send] = useActor(someMachine, {
    snapshot: persistedSnapshot
  });

  // snapshot will rehydrate the provided persisted snapshot, it won't be the machine's initial snapshot

  return (/* ... */)
}

Actor refs

The actorRef created in useActor(logic) can be referenced as the third returned value:

//                  vvvvvvv
const [snapshot, send, actorRef] = useActor(someMachine);

You can subscribe to that actorRef's snapshot changes with the createEffect hook:

// ...

createEffect(() => {
  const subscription = actorRef.subscribe((snapshot) => {
    // simple snapshot logging
    console.log(snapshot);
  });

  onCleanup(() => subscription.unsubscribe());
}); // note: service should never change
0.2.0

3 months ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago