UNPKG

jotai-valtio

Version:
82 lines (81 loc) • 2.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mutableAtom = mutableAtom; const vanilla_1 = require("jotai/vanilla"); const vanilla_2 = require("valtio/vanilla"); const utils_1 = require("valtio/vanilla/utils"); function mutableAtom(initialValue, options = defaultOptions) { const valueAtom = (0, vanilla_1.atom)({ value: initialValue }); if (process.env.NODE_ENV !== 'production') { valueAtom.debugPrivate = true; } const { proxyFn } = { ...defaultOptions, ...options }; const storeAtom = (0, vanilla_1.atom)((_get, { setSelf }) => { const store = { proxyState: createProxyState(() => store), getValue: () => setSelf({ type: 'getValue' }), setValue: (value) => setSelf({ type: 'setValue', payload: value }), }; return store; }, (get, set, action) => { if (action.type === 'setValue') { set(valueAtom, { value: action.payload }); } else if (action.type === 'getValue') { return get(valueAtom).value; } }); if (process.env.NODE_ENV !== 'production') { storeAtom.debugPrivate = true; } /** * sync the proxy state with the atom */ function onChange(getStore) { return () => { const { proxyState, getValue, setValue } = getStore(); const { value } = (0, vanilla_2.snapshot)(proxyState); if (!Object.is(value, getValue())) { setValue(value); } }; } /** * create the proxy state and subscribe to it */ function createProxyState(getStore) { const proxyState = proxyFn({ value: (0, utils_1.deepClone)(initialValue) }); // We never unsubscribe, but it's garbage collectable. (0, vanilla_2.subscribe)(proxyState, onChange(getStore), true); return proxyState; } /** * wrap the proxy state in a proxy to ensure rerender on value change */ function wrapProxyState(proxyState) { return new Proxy(proxyState, { get(target, property) { return target[property]; }, set(target, property, value) { if (property === 'value') { target[property] = value; return true; } return false; }, }); } /** * create an atom that returns the proxy state */ const proxyEffectAtom = (0, vanilla_1.atom)((get) => { get(valueAtom); // subscribe to value updates const store = get(storeAtom); return wrapProxyState(store.proxyState); }); return proxyEffectAtom; } const defaultOptions = { proxyFn: vanilla_2.proxy, };