UNPKG

redext

Version:

A simple global store based on React Context and Hooks

158 lines (146 loc) 4.39 kB
// src/connect.tsx import { useContext as useContext3 } from "react"; // src/Context.tsx import { createContext } from "react"; var Context_default = createContext({}); // src/hooks/useContextSelector.ts import { useContext, useSyncExternalStore } from "react"; // src/hooks/useDeepMemo.ts import React from "react"; // src/hooks/useDeepMemoize.ts import { useRef } from "react"; // src/utils/deepEqual.ts var equal = (a, b) => { let ctor; let len; if (a === b) { return true; } if (a && b && (ctor = a.constructor) === b.constructor) { if (ctor === Date) { return a.getTime() === b.getTime(); } if (ctor === RegExp) { return a.toString() === b.toString(); } if (ctor === Array && (len = a.length) === b.length) { while (len-- && equal(a[len], b[len])) ; return len === -1; } if (ctor === Object) { if (Object.keys(a).length !== Object.keys(b).length) { return false; } for (len in a) { if (!(len in b) || !equal(a[len], b[len])) { return false; } } return true; } } return a !== a && b !== b; }; function deepEqual(a, b) { try { return equal(a, b); } catch (error) { if (error.message && error.message.match(/stack|recursion/i) || error.number === -2146828260) { console.warn("Warning: deepEqual does not handle circular references.", error.name, error.message); return false; } throw error; } } // src/hooks/useDeepMemoize.ts var useDeepMemoize = (value) => { const ref = useRef([]); if (!deepEqual(value, ref.current)) { ref.current = value; } return ref.current; }; var useDeepMemoize_default = useDeepMemoize; // src/utils/checkDeps.ts var isPrimitive = (val) => { return val == null || /^[sbn]/.test(typeof val); }; var checkDeps = (deps, name) => { const hookName = `React.${name.replace(/Deep/, "")}`; if (!deps || deps.length === 0) { console.warn(`${name} should not be used with no dependencies. Use ${hookName} instead.`); } if (deps.every(isPrimitive)) { console.warn(`${name} should not be used with dependencies that are all primitive values. Use ${hookName} instead.`); } }; var checkDeps_default = checkDeps; // src/hooks/useDeepMemo.ts var useDeepMemo = (factory, dependencies) => { if (process.env.NODE_ENV !== "production") { checkDeps_default(dependencies, "useDeepMemo"); } return React.useMemo(factory, useDeepMemoize_default(dependencies)); }; var useDeepMemo_default = useDeepMemo; // src/hooks/useContextSelector.ts var useContextSelector = (mapStateToProps, params = {}) => { const { isWithSyncExternalStore = true } = params; if (isWithSyncExternalStore && useSyncExternalStore) { const { subscribe, getState } = useContext(Context_default); const getSnapshot = () => { if (!mapStateToProps) { return void 0; } const state2 = getState(); return mapStateToProps(state2); }; return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); } const { state = {} } = useContext(Context_default); let filteredState = {}; if (mapStateToProps) { filteredState = mapStateToProps(state); } else { filteredState = state; } return useDeepMemo_default(() => { return filteredState; }, [filteredState]); }; var useContextSelector_default = useContextSelector; // src/hooks/useDispatcher.ts import { useContext as useContext2 } from "react"; var useDispatcher = (mapDispatchToProps) => { const { dispatch, effects } = useContext2(Context_default); let filteredDispatch = {}; if (mapDispatchToProps) { filteredDispatch = mapDispatchToProps(effects, dispatch); } return filteredDispatch; }; var useDispatcher_default = useDispatcher; // src/connect.tsx import { jsx } from "react/jsx-runtime"; var connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return (props) => { const { dispatch } = useContext3(Context_default); const memoState = useContextSelector_default(mapStateToProps, { isWithSyncExternalStore: false }); const dispatcher = useDispatcher_default(mapDispatchToProps); return /* @__PURE__ */ jsx( Component, { ...props, ...memoState, ...dispatcher, dispatch } ); }; }; var connect_default = connect; export { connect_default as default };