@baqhub/sdk-react
Version:
The official React SDK for the BAQ federated app platform.
111 lines (110 loc) • 3.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useConstant = useConstant;
exports.useStable = useStable;
exports.useDeepMemo = useDeepMemo;
exports.abortable = abortable;
exports.useAbortable = useAbortable;
exports.useUnmountSignal = useUnmountSignal;
exports.useIsMounted = useIsMounted;
exports.useImageUrl = useImageUrl;
exports.useMergeWrap = useMergeWrap;
const tslib_1 = require("tslib");
const sdk_1 = require("@baqhub/sdk");
const isEqual_js_1 = tslib_1.__importDefault(require("lodash/isEqual.js"));
const react_1 = require("react");
function useConstant(builder) {
const valueRef = (0, react_1.useRef)(undefined);
if (!valueRef.current) {
valueRef.current = builder();
}
return valueRef.current;
}
function useStable(value) {
const valueRef = (0, react_1.useRef)(value);
(0, react_1.useEffect)(() => {
valueRef.current = value;
}, [value]);
return (0, react_1.useCallback)((...args) => {
const currentValue = valueRef.current;
if (!currentValue) {
return;
}
currentValue(...args);
}, []);
}
function useDeepMemo(memoFn, key) {
const value = (0, react_1.useRef)(undefined);
// eslint-disable-next-line react-hooks/exhaustive-deps
const result = value.current && (0, isEqual_js_1.default)(key, value.current.key)
? value.current
: { key, value: memoFn() };
(0, react_1.useEffect)(() => {
value.current = result;
}, [result]);
return result.value;
}
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 sdk_1.AbortedError) {
return;
}
throw error;
}
}
effectAsync();
return () => {
abort.abort();
};
}
function useAbortable(effect, deps) {
// eslint-disable-next-line react-hooks/exhaustive-deps
(0, react_1.useEffect)(() => abortable(effect), deps);
}
function useUnmountSignal() {
const abortRef = (0, react_1.useRef)(undefined);
const abort = (() => {
const currentAbort = abortRef.current;
if (currentAbort && !currentAbort.signal.aborted) {
return currentAbort;
}
return new AbortController();
})();
(0, react_1.useEffect)(() => {
abortRef.current = abort;
return () => {
abort.abort();
};
}, [abort]);
return abort.signal;
}
function useIsMounted() {
const isMountedRef = (0, react_1.useRef)(true);
(0, react_1.useEffect)(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
return { isMountedRef };
}
function useImageUrl(blob) {
const imageUrl = (0, react_1.useMemo)(() => URL.createObjectURL(blob), [blob]);
(0, react_1.useEffect)(() => () => URL.revokeObjectURL(imageUrl), [imageUrl]);
return imageUrl;
}
function useMergeWrap(firstWrapper, ...otherWrappers) {
return (0, react_1.useMemo)(() => {
return otherWrappers.reduce((acc, wrapper) => {
return children => acc(wrapper(children));
}, firstWrapper);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [firstWrapper, ...otherWrappers]);
}