UNPKG

jotai

Version:

👻 Next gen state management that will spook you

797 lines (786 loc) • 28.1 kB
import { createContext, useState, useEffect, useDebugValue, useRef, createElement, useContext, useCallback, useReducer } from 'react'; const SUSPENSE_PROMISE = Symbol(); const isSuspensePromise = (promise) => !!promise[SUSPENSE_PROMISE]; const isSuspensePromiseAlreadyCancelled = (suspensePromise) => !suspensePromise[SUSPENSE_PROMISE].c; const cancelSuspensePromise = (suspensePromise) => { var _a, _b; (_b = (_a = suspensePromise[SUSPENSE_PROMISE]).c) == null ? void 0 : _b.call(_a); }; const isEqualSuspensePromise = (oldSuspensePromise, newSuspensePromise) => { const oldOriginalPromise = oldSuspensePromise[SUSPENSE_PROMISE].o; const newOriginalPromise = newSuspensePromise[SUSPENSE_PROMISE].o; return oldOriginalPromise === newOriginalPromise || oldSuspensePromise === newOriginalPromise || isSuspensePromise(oldOriginalPromise) && isEqualSuspensePromise(oldOriginalPromise, newSuspensePromise); }; const createSuspensePromise = (promise) => { const objectToAttach = { o: promise, c: null }; const suspensePromise = new Promise((resolve) => { objectToAttach.c = () => { objectToAttach.c = null; resolve(); }; promise.then(objectToAttach.c, objectToAttach.c); }); suspensePromise[SUSPENSE_PROMISE] = objectToAttach; return suspensePromise; }; var __defProp$1 = Object.defineProperty; var __defProps$1 = Object.defineProperties; var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; var __hasOwnProp$1 = Object.prototype.hasOwnProperty; var __propIsEnum$1 = Object.prototype.propertyIsEnumerable; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$1 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); if (__getOwnPropSymbols$1) for (var prop of __getOwnPropSymbols$1(b)) { if (__propIsEnum$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); } return a; }; var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b)); const hasInitialValue = (atom) => "init" in atom; const READ_ATOM = "r"; const WRITE_ATOM = "w"; const COMMIT_ATOM = "c"; const SUBSCRIBE_ATOM = "s"; const RESTORE_ATOMS = "h"; const DEV_SUBSCRIBE_STATE = "n"; const DEV_GET_MOUNTED_ATOMS = "l"; const DEV_GET_ATOM_STATE = "a"; const DEV_GET_MOUNTED = "m"; const createStore = (initialValues) => { const committedAtomStateMap = /* @__PURE__ */ new WeakMap(); const mountedMap = /* @__PURE__ */ new WeakMap(); const pendingMap = /* @__PURE__ */ new Map(); let stateListeners; let mountedAtoms; if ((import.meta.env && import.meta.env.MODE) !== "production") { stateListeners = /* @__PURE__ */ new Set(); mountedAtoms = /* @__PURE__ */ new Set(); } if (initialValues) { for (const [atom, value] of initialValues) { const atomState = { v: value, r: 0, d: /* @__PURE__ */ new Map() }; if ((import.meta.env && import.meta.env.MODE) !== "production") { Object.freeze(atomState); if (!hasInitialValue(atom)) { console.warn("Found initial value for derived atom which can cause unexpected behavior", atom); } } committedAtomStateMap.set(atom, atomState); } } const suspensePromiseCacheMap = /* @__PURE__ */ new WeakMap(); const addSuspensePromiseToCache = (version, atom, suspensePromise) => { let cache = suspensePromiseCacheMap.get(atom); if (!cache) { cache = /* @__PURE__ */ new Map(); suspensePromiseCacheMap.set(atom, cache); } suspensePromise.then(() => { if (cache.get(version) === suspensePromise) { cache.delete(version); if (!cache.size) { suspensePromiseCacheMap.delete(atom); } } }); cache.set(version, suspensePromise); }; const cancelAllSuspensePromiseInCache = (atom) => { const versionSet = /* @__PURE__ */ new Set(); const cache = suspensePromiseCacheMap.get(atom); if (cache) { suspensePromiseCacheMap.delete(atom); cache.forEach((suspensePromise, version) => { cancelSuspensePromise(suspensePromise); versionSet.add(version); }); } return versionSet; }; const versionedAtomStateMapMap = /* @__PURE__ */ new WeakMap(); const getVersionedAtomStateMap = (version) => { let versionedAtomStateMap = versionedAtomStateMapMap.get(version); if (!versionedAtomStateMap) { versionedAtomStateMap = /* @__PURE__ */ new Map(); versionedAtomStateMapMap.set(version, versionedAtomStateMap); } return versionedAtomStateMap; }; const getAtomState = (version, atom) => { if (version) { const versionedAtomStateMap = getVersionedAtomStateMap(version); let atomState = versionedAtomStateMap.get(atom); if (!atomState) { atomState = getAtomState(version.p, atom); if (atomState) { if ("p" in atomState) { atomState.p.then(() => versionedAtomStateMap.delete(atom)); } versionedAtomStateMap.set(atom, atomState); } } return atomState; } return committedAtomStateMap.get(atom); }; const setAtomState = (version, atom, atomState) => { if ((import.meta.env && import.meta.env.MODE) !== "production") { Object.freeze(atomState); } if (version) { const versionedAtomStateMap = getVersionedAtomStateMap(version); versionedAtomStateMap.set(atom, atomState); } else { const prevAtomState = committedAtomStateMap.get(atom); committedAtomStateMap.set(atom, atomState); if (!pendingMap.has(atom)) { pendingMap.set(atom, prevAtomState); } } }; const createReadDependencies = (version, prevReadDependencies = /* @__PURE__ */ new Map(), dependencies) => { if (!dependencies) { return prevReadDependencies; } const readDependencies = /* @__PURE__ */ new Map(); let changed = false; dependencies.forEach((atom) => { var _a; const revision = ((_a = getAtomState(version, atom)) == null ? void 0 : _a.r) || 0; readDependencies.set(atom, revision); if (prevReadDependencies.get(atom) !== revision) { changed = true; } }); if (prevReadDependencies.size === readDependencies.size && !changed) { return prevReadDependencies; } return readDependencies; }; const setAtomValue = (version, atom, value, dependencies, suspensePromise) => { const atomState = getAtomState(version, atom); if (atomState) { if (suspensePromise && (!("p" in atomState) || !isEqualSuspensePromise(atomState.p, suspensePromise))) { return atomState; } if ("p" in atomState) { cancelSuspensePromise(atomState.p); } } const nextAtomState = { v: value, r: (atomState == null ? void 0 : atomState.r) || 0, d: createReadDependencies(version, atomState == null ? void 0 : atomState.d, dependencies) }; if (!atomState || !("v" in atomState) || !Object.is(atomState.v, value)) { ++nextAtomState.r; if (nextAtomState.d.has(atom)) { nextAtomState.d = new Map(nextAtomState.d).set(atom, nextAtomState.r); } } else if (nextAtomState.d !== atomState.d && (nextAtomState.d.size !== atomState.d.size || !Array.from(nextAtomState.d.keys()).every((a) => atomState.d.has(a)))) { Promise.resolve().then(() => { flushPending(version); }); } setAtomState(version, atom, nextAtomState); return nextAtomState; }; const setAtomReadError = (version, atom, error, dependencies, suspensePromise) => { const atomState = getAtomState(version, atom); if (atomState) { if (suspensePromise && (!("p" in atomState) || !isEqualSuspensePromise(atomState.p, suspensePromise))) { return atomState; } if ("p" in atomState) { cancelSuspensePromise(atomState.p); } } const nextAtomState = { e: error, r: (atomState == null ? void 0 : atomState.r) || 0, d: createReadDependencies(version, atomState == null ? void 0 : atomState.d, dependencies) }; setAtomState(version, atom, nextAtomState); return nextAtomState; }; const setAtomSuspensePromise = (version, atom, suspensePromise, dependencies) => { const atomState = getAtomState(version, atom); if (atomState && "p" in atomState) { if (isEqualSuspensePromise(atomState.p, suspensePromise)) { return atomState; } cancelSuspensePromise(atomState.p); } addSuspensePromiseToCache(version, atom, suspensePromise); const nextAtomState = { p: suspensePromise, r: (atomState == null ? void 0 : atomState.r) || 0, d: createReadDependencies(version, atomState == null ? void 0 : atomState.d, dependencies) }; setAtomState(version, atom, nextAtomState); return nextAtomState; }; const setAtomPromiseOrValue = (version, atom, promiseOrValue, dependencies) => { if (promiseOrValue instanceof Promise) { const suspensePromise = createSuspensePromise(promiseOrValue.then((value) => { setAtomValue(version, atom, value, dependencies, suspensePromise); flushPending(version); }).catch((e) => { if (e instanceof Promise) { if (isSuspensePromise(e)) { return e.then(() => { readAtomState(version, atom, true); }); } return e; } setAtomReadError(version, atom, e, dependencies, suspensePromise); flushPending(version); })); return setAtomSuspensePromise(version, atom, suspensePromise, dependencies); } return setAtomValue(version, atom, promiseOrValue, dependencies); }; const setAtomInvalidated = (version, atom) => { const atomState = getAtomState(version, atom); if (atomState) { if ("p" in atomState) { cancelSuspensePromise(atomState.p); } const nextAtomState = __spreadProps$1(__spreadValues$1({}, atomState), { i: atomState.r }); setAtomState(version, atom, nextAtomState); } else if ((import.meta.env && import.meta.env.MODE) !== "production") { console.warn("[Bug] could not invalidate non existing atom", atom); } }; const readAtomState = (version, atom, force) => { if (!force) { const atomState = getAtomState(version, atom); if (atomState) { if (atomState.r !== atomState.i && "p" in atomState && !isSuspensePromiseAlreadyCancelled(atomState.p)) { return atomState; } atomState.d.forEach((_, a) => { if (a !== atom) { if (!mountedMap.has(a)) { readAtomState(version, a); } else { const aState = getAtomState(version, a); if (aState && aState.r === aState.i) { readAtomState(version, a); } } } }); if (Array.from(atomState.d).every(([a, r]) => { const aState = getAtomState(version, a); return aState && "v" in aState && aState.r === r; })) { return atomState; } } } const dependencies = /* @__PURE__ */ new Set(); try { const promiseOrValue = atom.read((a) => { dependencies.add(a); const aState = a === atom ? getAtomState(version, a) : readAtomState(version, a); if (aState) { if ("e" in aState) { throw aState.e; } if ("p" in aState) { throw aState.p; } return aState.v; } if (hasInitialValue(a)) { return a.init; } throw new Error("no atom init"); }); return setAtomPromiseOrValue(version, atom, promiseOrValue, dependencies); } catch (errorOrPromise) { if (errorOrPromise instanceof Promise) { const suspensePromise = createSuspensePromise(errorOrPromise); return setAtomSuspensePromise(version, atom, suspensePromise, dependencies); } return setAtomReadError(version, atom, errorOrPromise, dependencies); } }; const readAtom = (readingAtom, version) => { const atomState = readAtomState(version, readingAtom); return atomState; }; const addAtom = (addingAtom) => { let mounted = mountedMap.get(addingAtom); if (!mounted) { mounted = mountAtom(addingAtom); } return mounted; }; const canUnmountAtom = (atom, mounted) => !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom)); const delAtom = (deletingAtom) => { const mounted = mountedMap.get(deletingAtom); if (mounted && canUnmountAtom(deletingAtom, mounted)) { unmountAtom(deletingAtom); } }; const invalidateDependents = (version, atom) => { const mounted = mountedMap.get(atom); mounted == null ? void 0 : mounted.t.forEach((dependent) => { if (dependent !== atom) { setAtomInvalidated(version, dependent); invalidateDependents(version, dependent); } }); }; const writeAtomState = (version, atom, update) => { let isSync = true; const writeGetter = (a, options) => { const aState = readAtomState(version, a); if ("e" in aState) { throw aState.e; } if ("p" in aState) { if (options == null ? void 0 : options.unstable_promise) { return aState.p.then(() => writeGetter(a, options)); } if ((import.meta.env && import.meta.env.MODE) !== "production") { console.info("Reading pending atom state in write operation. We throw a promise for now.", a); } throw aState.p; } if ("v" in aState) { return aState.v; } if ((import.meta.env && import.meta.env.MODE) !== "production") { console.warn("[Bug] no value found while reading atom in write operation. This is probably a bug.", a); } throw new Error("no value found"); }; const setter = (a, v) => { let promiseOrVoid2; if (a === atom) { if (!hasInitialValue(a)) { throw new Error("atom not writable"); } const versionSet = cancelAllSuspensePromiseInCache(a); versionSet.forEach((cancelledVersion) => { if (cancelledVersion !== version) { setAtomPromiseOrValue(cancelledVersion, a, v); } }); setAtomPromiseOrValue(version, a, v); invalidateDependents(version, a); } else { promiseOrVoid2 = writeAtomState(version, a, v); } if (!isSync) { flushPending(version); } return promiseOrVoid2; }; const promiseOrVoid = atom.write(writeGetter, setter, update); isSync = false; version = void 0; return promiseOrVoid; }; const writeAtom = (writingAtom, update, version) => { const promiseOrVoid = writeAtomState(version, writingAtom, update); flushPending(version); return promiseOrVoid; }; const isActuallyWritableAtom = (atom) => !!atom.write; const mountAtom = (atom, initialDependent) => { const mounted = { t: new Set(initialDependent && [initialDependent]), l: /* @__PURE__ */ new Set() }; mountedMap.set(atom, mounted); if ((import.meta.env && import.meta.env.MODE) !== "production") { mountedAtoms.add(atom); } const atomState = readAtomState(void 0, atom); atomState.d.forEach((_, a) => { const aMounted = mountedMap.get(a); if (aMounted) { aMounted.t.add(atom); } else { if (a !== atom) { mountAtom(a, atom); } } }); if (isActuallyWritableAtom(atom) && atom.onMount) { const setAtom = (update) => writeAtom(atom, update); const onUnmount = atom.onMount(setAtom); if (onUnmount) { mounted.u = onUnmount; } } return mounted; }; const unmountAtom = (atom) => { var _a; const onUnmount = (_a = mountedMap.get(atom)) == null ? void 0 : _a.u; if (onUnmount) { onUnmount(); } mountedMap.delete(atom); if ((import.meta.env && import.meta.env.MODE) !== "production") { mountedAtoms.delete(atom); } const atomState = getAtomState(void 0, atom); if (atomState) { atomState.d.forEach((_, a) => { if (a !== atom) { const mounted = mountedMap.get(a); if (mounted) { mounted.t.delete(atom); if (canUnmountAtom(a, mounted)) { unmountAtom(a); } } } }); } else if ((import.meta.env && import.meta.env.MODE) !== "production") { console.warn("[Bug] could not find atom state to unmount", atom); } }; const mountDependencies = (atom, atomState, prevReadDependencies) => { const dependencies = new Set(atomState.d.keys()); prevReadDependencies == null ? void 0 : prevReadDependencies.forEach((_, a) => { if (dependencies.has(a)) { dependencies.delete(a); return; } const mounted = mountedMap.get(a); if (mounted) { mounted.t.delete(atom); if (canUnmountAtom(a, mounted)) { unmountAtom(a); } } }); dependencies.forEach((a) => { const mounted = mountedMap.get(a); if (mounted) { mounted.t.add(atom); } else if (mountedMap.has(atom)) { mountAtom(a, atom); } }); }; const flushPending = (version) => { if (version) { const versionedAtomStateMap = getVersionedAtomStateMap(version); versionedAtomStateMap.forEach((atomState, atom) => { if (atomState !== committedAtomStateMap.get(atom)) { const mounted = mountedMap.get(atom); mounted == null ? void 0 : mounted.l.forEach((listener) => listener(version)); } }); return; } while (pendingMap.size) { const pending = Array.from(pendingMap); pendingMap.clear(); pending.forEach(([atom, prevAtomState]) => { const atomState = getAtomState(void 0, atom); if (atomState && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) { mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d); } const mounted = mountedMap.get(atom); mounted == null ? void 0 : mounted.l.forEach((listener) => listener()); }); } if ((import.meta.env && import.meta.env.MODE) !== "production") { stateListeners.forEach((l) => l()); } }; const commitVersionedAtomStateMap = (version) => { const versionedAtomStateMap = getVersionedAtomStateMap(version); versionedAtomStateMap.forEach((atomState, atom) => { const prevAtomState = committedAtomStateMap.get(atom); if (atomState.r > ((prevAtomState == null ? void 0 : prevAtomState.r) || 0) || "v" in atomState && atomState.r === (prevAtomState == null ? void 0 : prevAtomState.r) && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) { committedAtomStateMap.set(atom, atomState); if (atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) { mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d); } } }); }; const commitAtom = (_atom, version) => { if (version) { commitVersionedAtomStateMap(version); } flushPending(void 0); }; const subscribeAtom = (atom, callback) => { const mounted = addAtom(atom); const listeners = mounted.l; listeners.add(callback); return () => { listeners.delete(callback); delAtom(atom); }; }; const restoreAtoms = (values, version) => { for (const [atom, value] of values) { if (hasInitialValue(atom)) { setAtomPromiseOrValue(version, atom, value); invalidateDependents(version, atom); } } flushPending(version); }; if ((import.meta.env && import.meta.env.MODE) !== "production") { return { [READ_ATOM]: readAtom, [WRITE_ATOM]: writeAtom, [COMMIT_ATOM]: commitAtom, [SUBSCRIBE_ATOM]: subscribeAtom, [RESTORE_ATOMS]: restoreAtoms, [DEV_SUBSCRIBE_STATE]: (l) => { stateListeners.add(l); return () => { stateListeners.delete(l); }; }, [DEV_GET_MOUNTED_ATOMS]: () => mountedAtoms.values(), [DEV_GET_ATOM_STATE]: (a) => committedAtomStateMap.get(a), [DEV_GET_MOUNTED]: (a) => mountedMap.get(a) }; } return { [READ_ATOM]: readAtom, [WRITE_ATOM]: writeAtom, [COMMIT_ATOM]: commitAtom, [SUBSCRIBE_ATOM]: subscribeAtom, [RESTORE_ATOMS]: restoreAtoms }; }; const createStoreForExport = (initialValues) => { const store = createStore(initialValues); const get = (atom) => { const atomState = store[READ_ATOM](atom); if ("e" in atomState) { throw atomState.e; } if ("p" in atomState) { return void 0; } return atomState.v; }; const asyncGet = (atom) => new Promise((resolve, reject) => { const atomState = store[READ_ATOM](atom); if ("e" in atomState) { reject(atomState.e); } else if ("p" in atomState) { resolve(atomState.p.then(() => asyncGet(atom))); } else { resolve(atomState.v); } }); const set = (atom, update) => store[WRITE_ATOM](atom, update); const sub = (atom, callback) => store[SUBSCRIBE_ATOM](atom, callback); return { get, asyncGet, set, sub, SECRET_INTERNAL_store: store }; }; const createScopeContainer = (initialValues, unstable_createStore) => { const store = unstable_createStore ? unstable_createStore(initialValues).SECRET_INTERNAL_store : createStore(initialValues); return { s: store }; }; const ScopeContextMap = /* @__PURE__ */ new Map(); const getScopeContext = (scope) => { if (!ScopeContextMap.has(scope)) { ScopeContextMap.set(scope, createContext(createScopeContainer())); } return ScopeContextMap.get(scope); }; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); const atomToPrintable = (atom) => atom.debugLabel || atom.toString(); const stateToPrintable = ([store, atoms]) => Object.fromEntries(atoms.flatMap((atom) => { var _a, _b; const mounted = (_a = store[DEV_GET_MOUNTED]) == null ? void 0 : _a.call(store, atom); if (!mounted) { return []; } const dependents = mounted.t; const atomState = ((_b = store[DEV_GET_ATOM_STATE]) == null ? void 0 : _b.call(store, atom)) || {}; return [ [ atomToPrintable(atom), __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, "e" in atomState && { error: atomState.e }), "p" in atomState && { promise: atomState.p }), "v" in atomState && { value: atomState.v }), { dependents: Array.from(dependents).map(atomToPrintable) }) ] ]; })); const useDebugState = (scopeContainer) => { const { s: store } = scopeContainer; const [atoms, setAtoms] = useState([]); useEffect(() => { var _a; const callback = () => { var _a2; setAtoms(Array.from(((_a2 = store[DEV_GET_MOUNTED_ATOMS]) == null ? void 0 : _a2.call(store)) || [])); }; const unsubscribe = (_a = store[DEV_SUBSCRIBE_STATE]) == null ? void 0 : _a.call(store, callback); callback(); return unsubscribe; }, [store]); useDebugValue([store, atoms], stateToPrintable); }; const Provider = ({ children, initialValues, scope, unstable_createStore, unstable_enableVersionedWrite }) => { const [version, setVersion] = useState(); useEffect(() => { if (version) { scopeContainerRef.current.s[COMMIT_ATOM](null, version); delete version.p; } }, [version]); const scopeContainerRef = useRef(); if (!scopeContainerRef.current) { scopeContainerRef.current = createScopeContainer(initialValues, unstable_createStore); if (unstable_enableVersionedWrite) { scopeContainerRef.current.w = (write) => { setVersion((parentVersion) => { const nextVersion = parentVersion ? { p: parentVersion } : {}; write(nextVersion); return nextVersion; }); }; } } if ((import.meta.env && import.meta.env.MODE) !== "production" && !unstable_enableVersionedWrite) { useDebugState(scopeContainerRef.current); } const ScopeContainerContext = getScopeContext(scope); return createElement(ScopeContainerContext.Provider, { value: scopeContainerRef.current }, children); }; let keyCount = 0; function atom(read, write) { const key = `atom${++keyCount}`; const config = { toString: () => key }; if (typeof read === "function") { config.read = read; } else { config.init = read; config.read = (get) => get(config); config.write = (get, set, update) => set(config, typeof update === "function" ? update(get(config)) : update); } if (write) { config.write = write; } return config; } function useAtomValue(atom, scope) { const ScopeContext = getScopeContext(scope); const { s: store } = useContext(ScopeContext); const getAtomValue = useCallback((version2) => { const atomState = store[READ_ATOM](atom, version2); if ("e" in atomState) { throw atomState.e; } if ("p" in atomState) { throw atomState.p; } if ("v" in atomState) { return atomState.v; } throw new Error("no atom value"); }, [store, atom]); const [[version, value, atomFromUseReducer], rerenderIfChanged] = useReducer(useCallback((prev, nextVersion) => { const nextValue = getAtomValue(nextVersion); if (Object.is(prev[1], nextValue) && prev[2] === atom) { return prev; } return [nextVersion, nextValue, atom]; }, [getAtomValue, atom]), void 0, () => { const initialVersion = void 0; const initialValue = getAtomValue(initialVersion); return [initialVersion, initialValue, atom]; }); if (atomFromUseReducer !== atom) { rerenderIfChanged(void 0); } useEffect(() => { const unsubscribe = store[SUBSCRIBE_ATOM](atom, rerenderIfChanged); rerenderIfChanged(void 0); return unsubscribe; }, [store, atom]); useEffect(() => { store[COMMIT_ATOM](atom, version); }); useDebugValue(value); return value; } function useSetAtom(atom, scope) { const ScopeContext = getScopeContext(scope); const { s: store, w: versionedWrite } = useContext(ScopeContext); const setAtom = useCallback((update) => { if ((import.meta.env && import.meta.env.MODE) !== "production" && !("write" in atom)) { throw new Error("not writable atom"); } const write = (version) => store[WRITE_ATOM](atom, update, version); return versionedWrite ? versionedWrite(write) : write(); }, [store, versionedWrite, atom]); return setAtom; } function useAtom(atom, scope) { if ("scope" in atom) { console.warn("atom.scope is deprecated. Please do useAtom(atom, scope) instead."); scope = atom.scope; } return [ useAtomValue(atom, scope), useSetAtom(atom, scope) ]; } export { Provider, getScopeContext as SECRET_INTERNAL_getScopeContext, atom, createStoreForExport as unstable_createStore, useAtom, useAtomValue, useSetAtom };