Stately
XState v6 alpha

Input and restored snapshots

Start Vue actors with input or a persisted snapshot.

XState v6 is in alpha

APIs and behavior may change before the stable release.

input and snapshot are actor options, so they are passed as the second argument to useActor(...), useMachine(...) or useActorRef(...).

const { snapshot, send } = useActor(checkoutMachine, {
  input: { cartId },
  snapshot: restoredSnapshot
});

input creates a fresh initial state from data the actor needs when it starts. A persisted snapshot resumes an actor that already ran. Both are read once, when the component sets up.

Input from props

<script setup lang="ts">
const props = defineProps<{ cartId: string }>();

const { snapshot, send } = useActor(checkoutMachine, {
  input: { cartId: props.cartId }
});
</script>

Changing cartId later does not restart the actor, because the option was already consumed. Choose one of:

  • send an event, such as send({ type: 'cart.changed', cartId }), and model the change in the machine
  • give the component a :key="cartId" so Vue unmounts the old actor and mounts a new one

Machines that declare required input make the options argument mandatory in TypeScript.

Persisting a snapshot

actorRef.getPersistedSnapshot() returns a serializable value, including persisted children. Save it as the actor changes.

<script setup lang="ts">
import { onBeforeUnmount } from 'vue';
import { useActor } from '@xstate/vue';

const { snapshot, send, actorRef } = useActor(uploadMachine, {
  snapshot: loadSnapshot()
});

const subscription = actorRef.subscribe(() => {
  localStorage.setItem(
    'upload',
    JSON.stringify(actorRef.getPersistedSnapshot())
  );
});

onBeforeUnmount(() => subscription.unsubscribe());
</script>

Read it back before the actor is created:

function loadSnapshot() {
  const raw = localStorage.getItem('upload');
  if (!raw) return undefined;
  try {
    return JSON.parse(raw);
  } catch {
    return undefined;
  }
}

Stored snapshots are untrusted input. Validate them and fall back to undefined when they do not fit the current machine. See Persist and restore actors for versioning.

What restoring does

A restored actor starts in the persisted state. Actions that already ran are not re-executed. Invoked actors are restarted and spawned actors are restored recursively, so a machine restored inside uploading starts the upload request again.

Warning: Do not persist a snapshot that holds values which cannot survive JSON.stringify: DOM nodes, file handles, promises. Keep those out of context, or model them as invoked actors that are recreated on restore.

Cheatsheet

useActor(logic, { input });
useActor(logic, { snapshot: persisted });
useActorRef(logic, { input, snapshot });

actorRef.getPersistedSnapshot();

On this page