@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
JavaScript
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,
});
};