diff --git a/src/mutableAtom/index.ts b/src/mutableAtom/index.ts index d6705f3..c92056c 100644 --- a/src/mutableAtom/index.ts +++ b/src/mutableAtom/index.ts @@ -30,31 +30,28 @@ export function makeMutableAtom( const storeAtom = atom< Store, - [ActionWithPayload<'setValueAsync', Value> | Action<'mount'>], - void + [ActionWithPayload<'setValue', Value> | Action<'getValue'>], + void | Value >( - (get, { setSelf }) => ({ - proxyState: null, - getValue: () => get(valueAtom).value, - setValue: async (value: Value) => { - await defer() - setSelf({ type: 'setValueAsync', payload: value }) - }, - }), + (_get, { setSelf }) => { + const getValue = () => setSelf({ type: 'getValue' }) as Value + const store: Store = { + proxyState: createProxyState(getValue(), () => store), + getValue, + setValue: (value: Value) => + setSelf({ type: 'setValue', payload: value }) as void, + } + return store + }, (get, set, action) => { - if (action.type === 'setValueAsync') { + if (action.type === 'setValue') { set(valueAtom, { value: action.payload }) - } else if (action.type === 'mount') { - const store = get(storeAtom) - store.setValue = (value: Value) => { - set(valueAtom, { value }) - } + } else if (action.type === 'getValue') { + return get(valueAtom).value } } ) - storeAtom.onMount = (setAtom) => setAtom({ type: 'mount' }) - if (process.env.NODE_ENV !== 'production') { storeAtom.debugPrivate = true } @@ -65,9 +62,8 @@ export function makeMutableAtom( function onChange(getStore: () => Store) { return () => { const { proxyState, getValue, setValue } = getStore() - if (proxyState === null) return const { value } = snapshot(proxyState) - if (value !== getValue()) { + if (!Object.is(value, getValue())) { setValue(value as Awaited) } } @@ -76,23 +72,10 @@ export function makeMutableAtom( /** * create the proxy state and subscribe to it */ - function createProxyState(getStore: () => Store) { - const store = getStore() - const value = store.getValue() - store.proxyState ??= proxyFn({ value }) - store.proxyState.value = value - subscribe(store.proxyState, onChange(getStore), true) - return store.proxyState - } - - /** - * return the proxy if it exists, otherwise create and subscribe to it - */ - function ensureProxyState(getStore: () => Store) { - const { proxyState } = getStore() - if (proxyState === null) { - return createProxyState(getStore) - } + function createProxyState(initialValue: Value, getStore: () => Store) { + const proxyState = proxyFn({ value: initialValue }) + proxyState.value = initialValue + subscribe(proxyState, onChange(getStore), true) return proxyState } @@ -119,9 +102,8 @@ export function makeMutableAtom( */ const proxyEffectAtom = atom>((get) => { get(valueAtom) // subscribe to value updates - const getStore = () => get(storeAtom) - const proxyState = ensureProxyState(getStore) - return wrapProxyState(proxyState) + const store = get(storeAtom) + return wrapProxyState(store.proxyState) }) return proxyEffectAtom } @@ -129,10 +111,3 @@ export function makeMutableAtom( const defaultOptions = { proxyFn: proxy, } - -/** - * delays execution until next microtask - */ -function defer() { - return Promise.resolve().then() -} diff --git a/src/mutableAtom/types.ts b/src/mutableAtom/types.ts index 4e97150..4d72403 100644 --- a/src/mutableAtom/types.ts +++ b/src/mutableAtom/types.ts @@ -2,12 +2,10 @@ export type Wrapped = { value: T } type ProxyFn = (obj: Wrapped) => Wrapped -type PromiseOrValue = Promise | T - export type Store = { - proxyState: ProxyState | null + proxyState: ProxyState getValue: () => Value - setValue: (value: Value) => PromiseOrValue + setValue: (value: Value) => void } export type Options = {