import { MutableRefObject, useCallback, useRef, useState } from 'react'; import { ErrorMonitor, QueryResultStatus, queryStatus } from '@wix/bex-core'; import once from 'lodash/once'; export interface PromiseState { status: QueryResultStatus; fetchOnce: () => Promise>; promiseFnRef: MutableRefObject<(fn: () => Promise) => void>; } export function usePromiseState( _promiseFn: () => Promise, { errorMonitor, onError, }: { errorMonitor: ErrorMonitor; onError?: (params: { err: unknown; isOnline: boolean }) => unknown; }, ): PromiseState { const [status, setStatus] = useState>(() => ({ ...queryStatus.idle, error: null, isFetching: false, })); const promiseFnRef = useRef<() => Promise>(_promiseFn); const fetchOnce = useCallback( once(async () => { let newStatus: QueryResultStatus; try { setStatus({ ...queryStatus.loading, error: null, isFetching: true, }); const data = await promiseFnRef.current(); newStatus = { ...queryStatus.success, error: null, isFetching: false, data, }; setStatus(newStatus); } catch (err) { onError?.({ err, isOnline: true, }); errorMonitor.captureException(err); newStatus = { ...queryStatus.error, error: err, isFetching: false, }; setStatus(newStatus); } return newStatus; }), [], ); return { fetchOnce, status, promiseFnRef, }; }