Skip to content

Stopwatch with External React State

Stopped
elapsed0.0s
import { createMachine, defineStates, assignEventApi } from "matchina";
import { tickEffect } from "../lib/tick-effect";
export const createStopwatchMachine = (
elapsed: number,
setElapsed: (elapsed: number) => void
) => {
const effects = {
clear: () => setElapsed(0),
run: () => {
let lastTick = Date.now();
return tickEffect(() => {
const now = Date.now();
setElapsed(stopwatch.elapsed + now - lastTick);
lastTick = now;
});
},
};
const states = defineStates({
Stopped: { effects: [effects.clear] },
Ticking: { effects: [effects.run] },
Suspended: {},
});
const stopwatch = Object.assign(
assignEventApi(
createMachine(
states,
{
Stopped: {
start: "Ticking",
},
Ticking: {
stop: "Stopped",
suspend: "Suspended",
clear: "Ticking",
},
Suspended: {
stop: "Stopped",
resume: "Ticking",
clear: "Suspended",
},
},
"Stopped"
)
),
{
elapsed,
effects,
}
);
return stopwatch;
};