import { useReducer , useCallback , useRef , useState } from 'react' ; import { useDispatch , useSelector } from 'react-redux' ; import uniqueId from 'lodash/uniqueId' ; import type { State , Action } from '../types' ; import { PENDING } from './constants' ; import { getRequestById } from './selectors' ; import type { RequestState } from './types' ; type ActionWithRequestMeta = Action & { meta : { [ requestId ] : string ; } ; } ; export type DispatchApiRequestType = ( a : Action ) => ActionWithRequestMeta ; export type DispatchRequestsType = ( ... actions : Action [ ] ) => void ; returns { [ ( action : Action ) => unknown , string [ ] ] } example export function useDispatchApiRequest ( ) { const dispatch = useDispatch < ( a : Action ) => void > ( ) ; const [ requestIds , addRequestId ] = useReducer ( ( ids , next ) => [ ... ids , next ] , [ ] ) ; const dispatchApiRequest = useCallback ( ( a ) : ActionWithRequestMeta => { const requestId = uniqueId ( 'robotApi_request_' ) ; const action = { ... a , meta : { ... a . meta , requestId } } ; addRequestId ( requestId ) ; dispatch ( action ) ; return action ; } , [ dispatch ] ) ; return [ dispatchApiRequest , requestIds ] ; } returns { [ ( action : Action ) => unknown , string [ ] ] } example export function useDispatchApiRequests ( onDispatchedRequest = null ) { const [ dispatchRequest , requestIds ] = useDispatchApiRequest ( ) ; const trackedRequestId = useRef < string | null | undefined > ( null ) ; const [ unrequestedQueue , setUnrequestedQueue ] = useState < Action [ ] > ( [ ] ) ; const trackedRequestIsPending = useSelector < State , RequestState | null > ( state => { return trackedRequestId . current ? getRequestById ( state , trackedRequestId . current ) : null ; } ) ?. status === PENDING ; if ( unrequestedQueue . length > 0 && ! trackedRequestIsPending ) { const action = dispatchRequest ( unrequestedQueue [ 0 ] ) ; if ( onDispatchedRequest ) onDispatchedRequest ( action ) ; trackedRequestId . current = action . meta . requestId ; setUnrequestedQueue ( unrequestedQueue . slice ( 1 ) ) ; } const dispatchApiRequests = ( ... a ) : void => { setUnrequestedQueue ( [ ... unrequestedQueue , ... a ] ) ; } ; return [ dispatchApiRequests , requestIds ] ; }