forked from cassiozen/useStateMachine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.tsx
80 lines (73 loc) · 1.88 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import useStateMachine, {t} from '@cassiozen/usestatemachine';
import './index.css';
import formatTime from './formatTime';
/*
* In this example we simulate a somewhat complicated UI:
* there are multiple buttons but they can only appear when they can be used
*/
function App() {
const [machine, send] = useStateMachine({
schema: {
context: t<{time: number}>(),
},
context: {time: 0},
initial: 'idle',
verbose: true,
states: {
idle: {
on: {
START: {
target: 'running',
},
},
effect({ setContext }) {
setContext(() => ({ time: 0 }));
},
},
running: {
on: {
PAUSE: 'paused',
},
effect({ setContext }) {
const interval = setInterval(() => {
setContext(context => ({ time: context.time + 1 }));
}, 100);
return () => clearInterval(interval);
},
},
paused: {
on: {
RESET: 'idle',
START: {
target: 'running',
},
},
},
},
});
return (
<div className="StopWatch">
<div className="display">{formatTime(machine.context.time)}</div>
<div className="controls">
{machine.nextEvents?.includes('START') && (
<button type="button" onClick={() => send('START') }>
Start
</button>
)}
{machine.nextEvents?.includes('PAUSE') && (
<button type="button" onClick={() => send('PAUSE')}>
Pause
</button>
)}
{machine.nextEvents?.includes('RESET') && (
<button type="button" onClick={() => send('RESET')}>
Reset
</button>
)}
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));