UNPKG

@mongez/react-atom

Version:
99 lines (96 loc) 2.82 kB
"use client"; import { useAtom } from "./store.mjs"; import { useCallback, useEffect, useSyncExternalStore } from "react"; import { atomCollection, createAtom } from "@mongez/atom"; //#region ../@mongez/react-atom/src/react-atom.tsx /** * Build the React-aware action bag injected into every atom created via * the `atom()` factory in this package. * * Every hook in here goes through `useAtom(this)` first so that * components rendered inside an `<AtomStoreProvider>` operate on the * store-scoped clone, not the module-level template. * * Subscriptions are wired through `useSyncExternalStore` to keep React 18+ * concurrent rendering tear-free. */ function reactActions(data) { return { ...data.actions, Provider(props) { const atom = useAtom(this); useEffect(() => { atom.update(props.value); }, [props.value, atom]); return props.children; }, useWatch(key, callback) { const atom = useAtom(this); useEffect(() => { const sub = atom.watch(key, callback); return () => sub.unsubscribe(); }, [ atom, key, callback ]); }, useState() { const atom = useAtom(this); const subscribe = useCallback((onChange) => { const sub = atom.onChange(onChange); return () => sub.unsubscribe(); }, [atom]); const getSnapshot = useCallback(() => atom.value, [atom]); return [useSyncExternalStore(subscribe, getSnapshot, getSnapshot), useCallback((next) => { atom.update(next); }, [atom])]; }, useValue() { const atom = useAtom(this); const subscribe = useCallback((onChange) => { const sub = atom.onChange(onChange); return () => sub.unsubscribe(); }, [atom]); const getSnapshot = useCallback(() => atom.value, [atom]); return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); }, use(key) { const atom = useAtom(this); const subscribe = useCallback((onChange) => { const sub = atom.watch(key, onChange); return () => sub.unsubscribe(); }, [atom, key]); const getSnapshot = useCallback(() => atom.get(key), [atom, key]); return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); } }; } /** * Create a new React-aware atom. * * The returned atom carries hooks (`useState`, `useValue`, `use`, `useWatch`) * and a `<Provider>` component as instance methods. All hooks honor the * nearest `<AtomStoreProvider>` and use `useSyncExternalStore` underneath. */ function atom(data) { return createAtom({ ...data, actions: reactActions(data) }); } /** * Create a React-aware collection atom for working with arrays. */ function atomCollection$1(options) { return atomCollection({ ...options, actions: { ...options.actions, ...reactActions(options) } }); } //#endregion export { atom, atomCollection$1 as atomCollection }; //# sourceMappingURL=react-atom.mjs.map