-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathSleep.tsx
49 lines (40 loc) · 1.27 KB
/
Sleep.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
import React, { Reducer } from 'react';
import { useReducerAsync, AsyncActionHandlers } from 'use-reducer-async';
type State = {
sleeping: boolean;
};
const initialState: State = {
sleeping: false,
};
type Action =
| { type: 'START_SLEEP' }
| { type: 'END_SLEEP' };
const reducer: Reducer<State, Action> = (state, action) => {
switch (action.type) {
case 'START_SLEEP': return { ...state, sleeping: true };
case 'END_SLEEP': return { ...state, sleeping: false };
default: throw new Error('no such action type');
}
};
type AsyncAction = { type: 'SLEEP'; ms: number }
const asyncActionHandlers: AsyncActionHandlers<Reducer<State, Action>, AsyncAction> = {
SLEEP: ({ dispatch, signal }) => async (action) => {
dispatch({ type: 'START_SLEEP' });
const timer = setTimeout(() => {
dispatch({ type: 'END_SLEEP' });
}, action.ms);
signal.addEventListener('abort', () => {
clearTimeout(timer);
});
},
};
const Sleep: React.FC = () => {
const [state, dispatch] = useReducerAsync(reducer, initialState, asyncActionHandlers);
return (
<div>
<span>{state.sleeping ? 'Sleeping' : 'Idle'}</span>
<button type="button" onClick={() => dispatch({ type: 'SLEEP', ms: 1000 })}>Click</button>
</div>
);
};
export default Sleep;