UNPKG

@redotech/redo-hydrogen

Version:

Utilities to enable and disable Redo coverage on Hydrogen stores

50 lines (45 loc) 1.46 kB
import { DependencyList, useCallback, useEffect, useRef, useState, } from "react"; export interface Loader<T> { (abort: AbortSignal): Promise<T>; } export interface LoadState<T> { error?: any; pending: boolean; value?: T; } export function useLoad<T>(fn: Loader<T>, deps: DependencyList): LoadState<T> { const [state, setState] = useState<LoadState<T>>({ pending: false }); useEffect(() => { const abortController = new AbortController(); setState((state) => ({ ...state, pending: true })); fn(abortController.signal).then( (value) => setState({ pending: false, value }), (error) => { if ( !( error.message.includes("Request aborted for RPC method") || error.code === "ERR_CANCELED" || error.message === "Another request is in flight" ) ) { setState({ pending: false, error }); } }, ); return () => { abortController.abort(); setState((state) => ({ ...state, pending: false })); }; // The way useLoad() is designed, we have no choice but to trust that the user gave us the correct deps for fn(). // We could fix this by marking useLoad() as a custom hook, and then exhaustive-deps would enforce that for us. // https://www.npmjs.com/package/eslint-plugin-react-hooks#advanced-configuration // eslint-disable-next-line react-hooks/exhaustive-deps }, deps); return state; }