# Usage with Stencil
These XState v4 docs are no longer maintained
XState v5 is out now! Read more about XState v5 (opens new window) and check out the XState v5 docs (opens new window).
Stencil (opens new window) web components work very well with XState.
# src/helpers/toggle-machine.ts
import { createMachine } from 'xstate';
export const toggleMachine = createMachine({
id: 'toggle',
initial: 'active',
states: {
inactive: { on: { toggle: 'active' } },
active: { on: { toggle: 'inactive' } }
}
});
# src/components/toggle/toggle.tsx
Add a state
property to your component, decorated with @State
so that it triggers a re-render when changed.
On componentWillLoad
, interpret the toggleMachine
and listen for state transitions.
After a transition has occurred, the state
property is set to the machine's new state, triggering a re-render.
import { Component, h, State } from "@stencil/core";
import { interpret } from "xstate";
import { toggleMachine } from "../helpers/toggle-machine";
@Component({
tag: "my-toggle",
styleUrl: "toggle.css",
shadow: true
})
export class Toggle {
private _service = interpret(toggleMachine);
@State() state = this._service.getSnapshot();
componentWillLoad() {
this._service.subscribe(state => {
this.state = state;
});
this._service.start();
}
disconnectedCallback() {
this._service.stop();
}
render() {
const { send } = this._service;
return (
<button onClick={() => send("toggle")}>
{this.state.value === "inactive" ? "Off" : "On"}
</button>
);
}
}
Your html page:
<html>
<head>
<script type="module" src="/build/my-toggle.esm.js"></script>
<script nomodule src="/build/my-toggle.js"></script>
</head>
<body>
<my-toggle></my-toggle>
</body>
</html>