Skip to content

Instantly share code, notes, and snippets.

@RoyalIcing
Last active June 9, 2022 12:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RoyalIcing/229db1ce87ea3126c460d232cc1e6b0c to your computer and use it in GitHub Desktop.
Save RoyalIcing/229db1ce87ea3126c460d232cc1e6b0c to your computer and use it in GitHub Desktop.
Yieldmachine + React
import { start, on } from "https://unpkg.com/yieldmachine@0.5.1/dist/yieldmachine.module.js"
function TrafficLightsMachine() {
const { Green, Yellow, Red } = {
*Green() {
yield on("timer", Yellow);
},
*Yellow() {
yield on("timer", Red);
},
*Red() {
yield on("timer", Green);
}
};
return Red;
}
function useMachine(machineDefinition) {
const instance = useMemo(() => {
const aborter = new AbortController();
const machine = start(machineDefinition, { signal: aborter.signal });
return {
aborter, machine, dispatch: machine.next.bind(machine)
};
}, []);
useEffect(() => {
return () => {
instance.aborter.abort();
};
});
const state = useSyncExternalStore(
(callback) => {
instance.machine.eventTarget.addEventListener(
"StateChanged",
callback
);
return () => {
instance.machine.eventTarget.removeEventListener(
"StateChanged",
callback
);
};
},
() => instance.machine.value,
() => instance.machine.value
);
return Object.freeze([state, instance.dispatch]);
}
export default function App() {
const [value, dispatch] = useMachine(TrafficLightsMachine);
return <article class="flex flex-col gap-2 items-center text-lg">
<dl>
<div className="flex gap-2">
<dt className="font-bold">State:</dt>
<dd>{value.state}</dd>
</div>
<div className="flex gap-2">
<dt className="font-bold">Change</dt>
<dd>{"#"}{value.change}</dd>
</div>
</dl>
<button className="px-3 py-1 text-white bg-black rounded-lg" onClick={() => dispatch("timer")}>send event: timer</button>
</article>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment