UNPKG

@redotech/redo-hydrogen

Version:

Utilities to enable and disable Redo coverage on Hydrogen stores

46 lines (40 loc) 1.5 kB
import { DependencyList, useEffect, useState } from "react"; export interface Loader<T> { (abort: AbortSignal): Promise<T>; } export interface LoadState<T> { error?: unknown; 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: unknown) => { const message = error instanceof Error ? error.message : ""; const code = (error as Record<string, unknown>)?.code; if ( !( message.includes("Request aborted for RPC method") || code === "ERR_CANCELED" || 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 }, deps); return state; }