Skip to content

Instantly share code, notes, and snippets.

@drbr
Created November 26, 2020 07:26
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save drbr/c1bac785cd5e5739d264f9a2be3465d8 to your computer and use it in GitHub Desktop.
Save drbr/c1bac785cd5e5739d264f9a2be3465d8 to your computer and use it in GitHub Desktop.
XState Visualizer (XState Inspector) as a React component with a standalone state machine
import { useEffect, useState } from 'react';
import { StateMachine } from 'xstate';
import { useMachine } from '@xstate/react';
import { inspect } from '@xstate/inspect';
let iFrameElement: HTMLIFrameElement | null = null;
function createIFrame() {
if (!iFrameElement) {
const iframe = document.createElement('iframe');
iframe.setAttribute('id', 'xstate');
iframe.setAttribute('height', '100%');
iframe.setAttribute('width', '100%');
iframe.setAttribute('style', 'position: absolute; border: 0;');
document.body.appendChild(iframe);
iFrameElement = iframe;
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AnyStateMachine = StateMachine<any, any, any, any>;
export type XStateVizProps = {
machine: AnyStateMachine;
};
/**
* Renders the XState Inspector in a manner similar to the XState Visualizer (with a self-contained
* state machine), rather than connecting to an instance of the machine already running in an app.
*
* The iframe is set up to take up the whole page, so it's suggested that this be rendered in its
* own route or something similar.
*/
export function XStateViz(props: XStateVizProps) {
const [initialized, setInitialized] = useState(false);
useEffect(() => {
createIFrame();
inspect({
url: 'https://statecharts.io/inspect',
iframe: iFrameElement,
});
setInitialized(true);
}, []);
useEffect(() => {
document.title = props.machine.id;
});
if (initialized) {
return <StateMachineInstance {...props} />;
} else {
return null;
}
}
function StateMachineInstance(props: XStateVizProps) {
useMachine(props.machine, { devTools: true });
return <div></div>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment