swr-global-state
Version:
Zero-setup & simple global state management for React Components
150 lines (149 loc) • 3.73 kB
JavaScript
import { useMemo as O, useRef as x, useState as H, useCallback as w, useEffect as K } from "react";
import M, { useSWRConfig as q } from "swr";
function z(r, c) {
let t;
return { debouncedFunc: (...n) => {
clearTimeout(t), t = setTimeout(() => r(...n), c);
}, cleanup: () => {
clearTimeout(t);
} };
}
function A(r, c) {
let t = 0, u;
return { throttledFunc: (...a) => {
const o = Date.now();
o - t >= c ? (t = o, r(...a)) : (clearTimeout(u), u = setTimeout(() => {
t = Date.now(), r(...a);
}, c - (o - t)));
}, cleanup: () => {
clearTimeout(u);
} };
}
function B(r, c, t, u) {
if (c.customFunction)
return {
rateLimitedFunc: c.customFunction(r, c.delay),
cleanup: () => {
}
// Custom function should handle its own cleanup
};
const e = async (n, a) => {
t == null || t();
try {
await r(n, a);
} finally {
u == null || u();
}
};
switch (c.type) {
case "debounce": {
const { debouncedFunc: n, cleanup: a } = z(e, c.delay);
return { rateLimitedFunc: n, cleanup: a };
}
case "throttle": {
const { throttledFunc: n, cleanup: a } = A(e, c.delay);
return { rateLimitedFunc: n, cleanup: a };
}
default:
return {
rateLimitedFunc: e,
cleanup: () => {
}
};
}
}
function g(r, c) {
const {
key: t,
initial: u,
persistor: e,
onError: n,
retryOnError: a = !0,
rateLimit: o
} = r, d = O(() => (t == null ? void 0 : t.toString()) || "", [t]), { cache: h } = q(), l = x(null), [y, p] = H(!1), L = w(() => !(e != null && e.onSet) || !o ? null : B(
async (f, s) => {
try {
await Promise.resolve(e.onSet(f, s));
} catch (m) {
if (n == null || n(m), !a)
throw m;
}
},
o,
() => p(!0),
() => p(!1)
), [e == null ? void 0 : e.onSet, o, n, a]);
K(() => {
if (o && !l.current) {
const i = L();
i && (l.current = {
func: i.rateLimitedFunc,
cleanup: i.cleanup
});
}
return () => {
l.current && (l.current.cleanup(), l.current = null);
};
}, [o, L]);
const G = w(async () => {
var i, f;
try {
const s = (i = h.get(d)) == null ? void 0 : i.data;
return e != null && e.onGet ? s === void 0 ? await Promise.resolve(e.onGet(t)) ?? u : s : s ?? u;
} catch (s) {
if (n == null || n(s), a)
throw s;
return ((f = h.get(d)) == null ? void 0 : f.data) ?? u;
}
}, [h, d, e == null ? void 0 : e.onGet, t, u, n, a]), F = M(t, G, {
fallbackData: u,
revalidateOnFocus: !1,
revalidateOnReconnect: !1,
refreshWhenHidden: !1,
refreshWhenOffline: !1,
...c
}), { data: P, mutate: b, error: C, isLoading: D } = F, I = w(async (i, f) => b(async (s) => {
var v;
const m = s ?? ((v = h.get(d)) == null ? void 0 : v.data) ?? P, R = async (W) => {
if (e != null && e.onSet)
if (l.current)
l.current.func(t, W);
else
try {
await Promise.resolve(e.onSet(t, W));
} catch (T) {
if (n == null || n(T), !a)
throw T;
}
};
if (typeof i != "function")
return await R(i), i;
const j = i, S = await Promise.resolve(j(m));
return await R(S), S;
}, f), [b, t, e == null ? void 0 : e.onSet, n, a, d]), k = O(() => ({
...F,
isLoading: D,
error: C,
isPersisting: y
}), [F, D, C, y]);
return [
P,
I,
k
];
}
function J(r, c) {
return (t) => g({
...r,
initial: t ?? r.initial
}, c);
}
const U = {
createStore: J,
useStore: g
};
export {
J as createStore,
U as default,
g as useStore
};