UNPKG

@baqhub/sdk-react

Version:

The official React SDK for the BAQ federated app platform.

99 lines (98 loc) 2.9 kB
import { AbortedError } from "@baqhub/sdk"; import isEqual from "lodash/isEqual.js"; import { useCallback, useEffect, useMemo, useRef, } from "react"; export function useConstant(builder) { const valueRef = useRef(undefined); if (!valueRef.current) { valueRef.current = builder(); } return valueRef.current; } export function useStable(value) { const valueRef = useRef(value); useEffect(() => { valueRef.current = value; }, [value]); return useCallback((...args) => { const currentValue = valueRef.current; if (!currentValue) { return; } currentValue(...args); }, []); } export function useDeepMemo(memoFn, key) { const value = useRef(undefined); // eslint-disable-next-line react-hooks/exhaustive-deps const result = value.current && isEqual(key, value.current.key) ? value.current : { key, value: memoFn() }; useEffect(() => { value.current = result; }, [result]); return result.value; } export function abortable(worker) { const abort = new AbortController(); // Catch aborted errors. async function effectAsync() { try { await null; await Promise.resolve(worker(abort.signal)); } catch (error) { if (error instanceof AbortedError) { return; } throw error; } } effectAsync(); return () => { abort.abort(); }; } export function useAbortable(effect, deps) { // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => abortable(effect), deps); } export function useUnmountSignal() { const abortRef = useRef(undefined); const abort = (() => { const currentAbort = abortRef.current; if (currentAbort && !currentAbort.signal.aborted) { return currentAbort; } return new AbortController(); })(); useEffect(() => { abortRef.current = abort; return () => { abort.abort(); }; }, [abort]); return abort.signal; } export function useIsMounted() { const isMountedRef = useRef(true); useEffect(() => { isMountedRef.current = true; return () => { isMountedRef.current = false; }; }, []); return { isMountedRef }; } export function useImageUrl(blob) { const imageUrl = useMemo(() => URL.createObjectURL(blob), [blob]); useEffect(() => () => URL.revokeObjectURL(imageUrl), [imageUrl]); return imageUrl; } export function useMergeWrap(firstWrapper, ...otherWrappers) { return useMemo(() => { return otherWrappers.reduce((acc, wrapper) => { return children => acc(wrapper(children)); }, firstWrapper); // eslint-disable-next-line react-hooks/exhaustive-deps }, [firstWrapper, ...otherWrappers]); }