From f95519fd227a4aabea849aed86a3b50ce360fb6f Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 6 Oct 2023 11:11:19 +0900 Subject: [PATCH 1/5] refactor --- src/mutableAtom/index.ts | 69 +++++++++++++--------------------------- src/mutableAtom/types.ts | 6 ++-- 2 files changed, 24 insertions(+), 51 deletions(-) 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 = { From 2e71d8c0d63e969249f8326a9dbac6d84d57749a Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 6 Oct 2023 11:15:44 +0900 Subject: [PATCH 2/5] remove a line and add a comment --- src/mutableAtom/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mutableAtom/index.ts b/src/mutableAtom/index.ts index c92056c..d3ca809 100644 --- a/src/mutableAtom/index.ts +++ b/src/mutableAtom/index.ts @@ -74,7 +74,7 @@ export function makeMutableAtom( */ function createProxyState(initialValue: Value, getStore: () => Store) { const proxyState = proxyFn({ value: initialValue }) - proxyState.value = initialValue + // We never unsubscribe, but it's garbage collectable. subscribe(proxyState, onChange(getStore), true) return proxyState } From f6e65fc4ec14befe83ba54146168952cfea37b1c Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 6 Oct 2023 12:24:04 +0900 Subject: [PATCH 3/5] refactor again --- src/mutableAtom/index.ts | 19 +++++-------------- src/mutableAtom/types.ts | 2 -- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/mutableAtom/index.ts b/src/mutableAtom/index.ts index d3ca809..ac6555f 100644 --- a/src/mutableAtom/index.ts +++ b/src/mutableAtom/index.ts @@ -1,5 +1,4 @@ import { atom } from 'jotai' -import type { PrimitiveAtom } from 'jotai' import { proxy, snapshot, subscribe } from 'valtio' import type { Action, @@ -7,25 +6,18 @@ import type { Options, ProxyState, Store, - Wrapped, } from './types' export function mutableAtom( - value: Value, + initialValue: Value, options: Options = defaultOptions ) { - const valueAtom = atom({ value }) + const valueAtom = atom({ value: initialValue }) if (process.env.NODE_ENV !== 'production') { valueAtom.debugPrivate = true } - return makeMutableAtom(valueAtom, options) -} -export function makeMutableAtom( - valueAtom: PrimitiveAtom>, - options: Options = defaultOptions -) { const { proxyFn } = { ...defaultOptions, ...options } const storeAtom = atom< @@ -34,10 +26,9 @@ export function makeMutableAtom( void | Value >( (_get, { setSelf }) => { - const getValue = () => setSelf({ type: 'getValue' }) as Value const store: Store = { - proxyState: createProxyState(getValue(), () => store), - getValue, + proxyState: createProxyState(() => store), + getValue: () => setSelf({ type: 'getValue' }) as Value, setValue: (value: Value) => setSelf({ type: 'setValue', payload: value }) as void, } @@ -72,7 +63,7 @@ export function makeMutableAtom( /** * create the proxy state and subscribe to it */ - function createProxyState(initialValue: Value, getStore: () => Store) { + function createProxyState(getStore: () => Store) { const proxyState = proxyFn({ value: initialValue }) // We never unsubscribe, but it's garbage collectable. subscribe(proxyState, onChange(getStore), true) diff --git a/src/mutableAtom/types.ts b/src/mutableAtom/types.ts index 4d72403..27db076 100644 --- a/src/mutableAtom/types.ts +++ b/src/mutableAtom/types.ts @@ -1,5 +1,3 @@ -export type Wrapped = { value: T } - type ProxyFn = (obj: Wrapped) => Wrapped export type Store = { From f95dc75e2d5f15b850ee9d74bddf1acb8174438c Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 6 Oct 2023 12:36:48 +0900 Subject: [PATCH 4/5] oops --- src/mutableAtom/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mutableAtom/types.ts b/src/mutableAtom/types.ts index 27db076..62ab9db 100644 --- a/src/mutableAtom/types.ts +++ b/src/mutableAtom/types.ts @@ -1,3 +1,5 @@ +type Wrapped = { value: T } + type ProxyFn = (obj: Wrapped) => Wrapped export type Store = { From 87fd800e8e6df47832537e7e13186cc0e38a6e56 Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 6 Oct 2023 13:32:34 +0900 Subject: [PATCH 5/5] fix imports --- src/mutableAtom/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mutableAtom/index.ts b/src/mutableAtom/index.ts index ac6555f..4a06d51 100644 --- a/src/mutableAtom/index.ts +++ b/src/mutableAtom/index.ts @@ -1,5 +1,5 @@ -import { atom } from 'jotai' -import { proxy, snapshot, subscribe } from 'valtio' +import { atom } from 'jotai/vanilla' +import { proxy, snapshot, subscribe } from 'valtio/vanilla' import type { Action, ActionWithPayload,