Last active
January 5, 2023 17:42
-
-
Save luisherranz/ec16177c07efb6a50e89b50dda08f7e8 to your computer and use it in GitHub Desktop.
Preact Deep Signals
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { signal } from '@preact/signals'; | |
const proxyToSignals = new WeakMap(); | |
const objToProxy = new WeakMap(); | |
export const deepSignal = (obj) => new Proxy(obj, handlers); | |
export const options = { returnSignal: /^\$/ }; | |
const handlers = { | |
get(target, prop, receiver) { | |
const returnSignal = options.returnSignal.test(prop); | |
const key = returnSignal ? prop.replace(options.returnSignal, '') : prop; | |
if (!proxyToSignals.has(receiver)) proxyToSignals.set(receiver, new Map()); | |
const signals = proxyToSignals.get(receiver); | |
if (!signals.has(key)) { | |
let val = Reflect.get(target, key, receiver); | |
if (typeof val === 'object' && val !== null) { | |
if (!objToProxy.has(val)) objToProxy.set(val, new Proxy(val, handlers)); | |
val = objToProxy.get(val); | |
} | |
signals.set(key, signal(val)); | |
} | |
return returnSignal ? signals.get(key) : signals.get(key).value; | |
}, | |
set(target, prop, val, receiver) { | |
let internal = val; | |
if (typeof val === 'object' && val !== null) { | |
if (!objToProxy.has(val)) objToProxy.set(val, new Proxy(val, handlers)); | |
internal = objToProxy.get(val); | |
} | |
if (!proxyToSignals.has(receiver)) proxyToSignals.set(receiver, new Map()); | |
const signals = proxyToSignals.get(receiver); | |
if (!signals.has(prop)) signals.set(prop, signal(internal)); | |
else signals.get(prop).value = internal; | |
return Reflect.set(target, prop, val, receiver); | |
}, | |
}; |
I moved it to a repo and published it on npm
:
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Stackblitz with example