UNPKG

@mittwald/react-use-promise

Version:

Simple and declarative use of Promises in your React components. Observe their state and refresh them in various advanced ways.

84 lines (83 loc) 2.94 kB
import { hash } from "object-code"; import { useEffect, useMemo } from "react"; import { useOnVisibilityChange } from "../lib/useOnVisibilityChange.js"; import { useOnWindowFocused } from "../lib/useOnWindowFocused.js"; import { useWatchObservableValue } from "../observable-value/useWatchObservableValue.js"; export const useWatchResourceValue = (resource, options = {}) => { const { keepValueWhileLoading = true, useSuspense = true, refreshOnWindowFocus = false, refreshOnDocumentVisibilityChange = refreshOnWindowFocus, autoRefresh, } = options; const observedValue = useWatchObservableValue(useSuspense && keepValueWhileLoading ? resource.valueWithCache : resource.value); const error = useWatchObservableValue(resource.error); const previousValue = useMemo(() => ({ current: observedValue }), [resource]); useEffect(() => resource.onRefresh(() => { resource.load(); }), [resource]); useEffect(() => { if (autoRefresh) { return resource.addTTL(autoRefresh); } }, [resource, hash(autoRefresh)]); useOnWindowFocused(() => { if (refreshOnWindowFocus) { resource.refresh(); } }, [resource, refreshOnWindowFocus]); useOnVisibilityChange((isVisible) => { if (refreshOnDocumentVisibilityChange && isVisible) { resource.refresh(); } }, [resource, refreshOnDocumentVisibilityChange]); resource.load(); if (resource.syncValue.isSet) { if (useSuspense) { return resource.syncValue.value; } return Object.freeze({ maybeValue: resource.syncValue.value, value: resource.syncValue.value, hasValue: true, isLoading: false, }); } if (resource.syncError.isSet) { throw resource.syncError.value; } if (observedValue.isSet) { previousValue.current = observedValue; if (useSuspense) { return observedValue.value; } return Object.freeze({ maybeValue: observedValue.value, value: observedValue.value, hasValue: true, isLoading: false, }); } if (keepValueWhileLoading && previousValue.current.isSet) { if (useSuspense) { return previousValue.current.value; } return Object.freeze({ maybeValue: previousValue.current.value, value: previousValue.current.value, hasValue: true, isLoading: true, }); } if (error.isSet) { throw error.value; } if (useSuspense) { if (resource.suspensePromise === undefined) { throw new Error("Invariant violation: Unexpected state"); } throw resource.suspensePromise; } return Object.freeze({ maybeValue: undefined, hasValue: false, isLoading: true, }); };