( performAction: (item: T) => mixed | Promise<mixed>, canProcess: boolean = true, )
| 7 | }; |
| 8 | |
| 9 | function useActionsQueue<T>( |
| 10 | performAction: (item: T) => mixed | Promise<mixed>, |
| 11 | canProcess: boolean = true, |
| 12 | ): MessageQueueHook<T> { |
| 13 | const [queue, setQueue] = React.useState<$ReadOnlyArray<T>>([]); |
| 14 | const isProcessing = React.useRef(false); |
| 15 | |
| 16 | const process = React.useCallback( |
| 17 | async (action: T) => { |
| 18 | isProcessing.current = true; |
| 19 | try { |
| 20 | await performAction(action); |
| 21 | } finally { |
| 22 | isProcessing.current = false; |
| 23 | setQueue(currentQueue => currentQueue.slice(1)); |
| 24 | } |
| 25 | }, |
| 26 | [performAction], |
| 27 | ); |
| 28 | |
| 29 | const enqueue = React.useCallback( |
| 30 | (items: $ReadOnlyArray<T>) => |
| 31 | setQueue(prevQueue => [...prevQueue, ...items]), |
| 32 | [], |
| 33 | ); |
| 34 | |
| 35 | React.useEffect(() => { |
| 36 | if (isProcessing.current || queue.length === 0 || !canProcess) { |
| 37 | return; |
| 38 | } |
| 39 | void process(queue[0]); |
| 40 | }, [process, queue, canProcess]); |
| 41 | |
| 42 | return { enqueue }; |
| 43 | } |
| 44 | |
| 45 | export { useActionsQueue }; |
no outgoing calls
no test coverage detected