UNPKG

swr-global-state

Version:

Zero-setup & simple global state management for React Components

150 lines (149 loc) 3.73 kB
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 };