# 与 Stencil 一起使用

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>