I want to use a state machine where the current state is mapped to the current screen. I am using svelte with xstate.
Example with string as type:
App.svelte
<script> import { interpret } from "xstate"; import { toggleMachine } from "./machine"; const toggleService = interpret(toggleMachine).start(); </script> <button on:click={() => toggleService.send("TOGGLE")}> <p>{$toggleService.value}</p> </button>
machine.js
import { createMachine } from 'xstate'; // This machine is completely decoupled from Svelte export const toggleMachine = createMachine({ id: 'toggle', initial: 'LOGIN', states: { LOBBY: { on: { TOGGLE: 'LOGIN' } }, LOGIN: { on: { TOGGLE: 'LOBBY' } } } });
How to do the same with a svelte component instead of a string?
Instead of <p>{$toggleService.value}</p>
something like this <$toggleService.value />
Edit: What I tried:
- Create Lobby and Login svelte component Login.svelte
<script lang="ts"> </script> <main> <h1>Login</h1> </main> <style> </style>
Lobby.svelte
<script lang="ts"> </script> <main> <h1>Lobby</h1> </main> <style> </style>
- Use them in machine.js
import { createMachine } from 'xstate'; import Login from './Login.svelte' import Lobby from './Lobby.svelte' // This machine is completely decoupled from Svelte export const toggleMachine = createMachine({ id: 'toggle', initial: Login, states: { Login: { on: { TOGGLE: Lobby } }, Lobby: { on: { TOGGLE: Login } } } });
- Use state machine in App.svelte App.svelte
<script> import { interpret } from "xstate"; import { toggleMachine } from "./machine"; const toggleService = interpret(toggleMachine).start(); </script> <button on:click={() => toggleService.send("TOGGLE")}> <$toggleService.value /> </button>
I get the error:
[!] (plugin svelte) ParseError: Expected valid tag name src/App.svelte 7: 8: <button on:click={() => toggleService.send("TOGGLE")}> 9: <$toggleService.value /> ^ 10: </button> ParseError: Expected valid tag name at error (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/utils/error.ts:25:16) at Parser$1.error (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/index.ts:101:3) at read_tag_name (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/state/tag.ts:267:10) at tag (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/state/tag.ts:77:15) at new Parser$1 (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/index.ts:53:12) at parse (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/index.ts:218:17) at compile (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/compile/index.ts:93:14) at Object.transform (/home/walde/projects/svelte/xstate/node_modules/rollup-plugin-svelte/index.js:111:21) at /home/walde/projects/svelte/xstate/node_modules/rollup/dist/shared/rollup.js:20218:25
Advertisement
Answer
I can’t speak for the xstate-part, but the last snippet is definitely not working. You can’t dynamically declare a tag like this. But you can use the special <svelte:component>
element for this:
<script> import { interpret } from "xstate"; import { toggleMachine } from "./machine"; const toggleService = interpret(toggleMachine).start(); </script> <button on:click={() => toggleService.send("TOGGLE")}> Toggle me </button> <svelte:component this={$toggleService.value} />