import { useEffect , useCallback , useState , useRef , useMemo } from 'react' ; import { HttpSetup } from '../../../../../src/core/public' ; import { sendRequest , SendRequestConfig } from './send_request' ; export interface UseRequestConfig extends SendRequestConfig { pollIntervalMs ? : number ; initialData ? : any ; deserializer ? : ( data : any ) => any ; } export interface UseRequestResponse < D = any , E = Error > { isInitialRequest : boolean ; isLoading : boolean ; error : E | null ; data ? : D | null ; resendRequest : ( ) => void ; } export const useRequest = < D = any , E = Error > ( httpClient , { path , method , query , body , pollIntervalMs , initialData , deserializer } ) : UseRequestResponse < D , E > => { const isMounted = useRef ( false ) ; const [ error , setError ] = useState < null | any > ( null ) ; const [ isLoading , setIsLoading ] = useState < boolean > ( true ) ; const [ data , setData ] = useState < any > ( initialData ) ; const requestCountRef = useRef < number > ( 0 ) ; const isInitialRequestRef = useRef < boolean > ( true ) ; const pollIntervalIdRef = useRef < any > ( null ) ; const clearPollInterval = useCallback ( ( ) => { if ( pollIntervalIdRef . current ) { clearTimeout ( pollIntervalIdRef . current ) ; pollIntervalIdRef . current = null ; } } , [ ] ) ; const queryStringified = query ? JSON . stringify ( query ) : undefined ; const bodyStringified = body ? JSON . stringify ( body ) : undefined ; const requestBody = useMemo ( ( ) => { return { path , method , query : queryStringified ? query : undefined , body : bodyStringified ? body : undefined , } ; } , [ path , method , queryStringified , bodyStringified ] ) ; const resendRequest = useCallback ( async ( ) => { clearPollInterval ( ) ; const requestId = ++ requestCountRef . current ; setIsLoading ( true ) ; const response = await sendRequest < D , E > ( httpClient , requestBody ) ; const { data : serializedResponseData , error : responseError } = response ; const isOutdatedRequest = requestId !== requestCountRef . current ; const isUnmounted = isMounted . current === false ; if ( isOutdatedRequest || isUnmounted ) { return ; } isInitialRequestRef . current = false ; setError ( responseError ) ; if ( ! responseError ) { const responseData = deserializer ? deserializer ( serializedResponseData ) : serializedResponseData ; setData ( responseData ) ; } setIsLoading ( false ) ; } , [ requestBody , httpClient , deserializer , clearPollInterval ] ) ; const scheduleRequest = useCallback ( ( ) => { clearPollInterval ( ) ; if ( pollIntervalMs ) { pollIntervalIdRef . current = setTimeout ( resendRequest , pollIntervalMs ) ; } } , [ pollIntervalMs , resendRequest , clearPollInterval ] ) ; useEffect ( ( ) => { resendRequest ( ) ; } , [ resendRequest ] ) ; useEffect ( ( ) => { if ( ! isLoading ) { scheduleRequest ( ) ; } } , [ isLoading , scheduleRequest ] ) ; useEffect ( ( ) => { isMounted . current = true ; return ( ) => { isMounted . current = false ; clearPollInterval ( ) ; } ; } , [ clearPollInterval ] ) ; return { isInitialRequest : isInitialRequestRef . current , isLoading , error , data , resendRequest , } ; } ;