github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/dashboard/frontend/src/hooks/useApiData.ts (about)

     1  import { useState, useEffect, useCallback } from 'react'
     2  import bluebird from 'bluebird'
     3  import useApi from './useApi'
     4  import { logger } from '../utils/debug'
     5  
     6  export function useApiData<DataType = any>({
     7    url,
     8    defaultValue,
     9    active = true,
    10    reload = false,
    11    reloadInterval = 5000,
    12    jsonStringifyComparison = true,
    13    onChange = () => {},
    14  }: {
    15    url: string,
    16    defaultValue: DataType,
    17    active?: boolean,
    18    reload?: boolean,
    19    reloadInterval?: number,
    20    // if this is set to false - we use JSON.stringify comparison
    21    // and don't update the state if equal
    22    jsonStringifyComparison?: boolean,
    23    onChange?: {
    24      (data: DataType): void,
    25    }
    26  }): [DataType, {
    27    (): Promise<void>,
    28  }] {
    29  
    30    const api = useApi()
    31    const [data, setData] = useState<DataType>(defaultValue)
    32  
    33    const fetchData = useCallback(async () => {
    34      const apiData = await api.get<DataType>(url)
    35      if (apiData === null) return
    36      // only update the state if the data is different
    37      // this prevents re-renders whilst loading data in a loop
    38      setData(currentValue => {
    39        if(!jsonStringifyComparison) return apiData
    40        const hasChanged = JSON.stringify(apiData) != JSON.stringify(currentValue)
    41        if(hasChanged && onChange) onChange(apiData)
    42        return hasChanged ?
    43          apiData :
    44          currentValue
    45      })
    46    }, [
    47      url,
    48    ])
    49  
    50    useEffect(() => {
    51      if(!active) return
    52      if(!reload) {
    53        fetchData()
    54        return  
    55      }
    56      let loading = true
    57      const doLoop = async () => {
    58        while(loading) {
    59          await fetchData()
    60          await bluebird.delay(reloadInterval)
    61        }
    62      }
    63      doLoop()
    64      return () => {
    65        loading = false
    66      }
    67    }, [
    68      active,
    69      url,
    70    ])
    71  
    72    useEffect(() => {
    73      logger('useApiData', url, data)
    74    }, [
    75      data,
    76    ])
    77  
    78    return [data, fetchData]
    79  }
    80  
    81  export default useApiData