Skip to content

Commit d0dcc55

Browse files
committed
Adjust how the proxy functions for useObject
No longer uses `revoke()`
1 parent 2391dd6 commit d0dcc55

File tree

2 files changed

+28
-45
lines changed

2 files changed

+28
-45
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-exo-hooks",
3-
"version": "1.0.2",
3+
"version": "2.0.0",
44
"module": "index.ts",
55
"main": "dist/index.js",
66
"description": "A collection of useful hooks for data structures and logic, designed for efficiency",

src/hooks/use-object.ts

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,84 +15,67 @@ function isPlainObject (value: unknown): value is object {
1515

1616
/**
1717
* Proxy an object recursively
18-
* @param object The object
19-
* @param setSignal The signal dispatch fn
20-
* @returns The proxied object
18+
* @param object The object
19+
* @param update The function that updates the signal
20+
* @returns The proxied object
2121
*/
22-
function proxyObject<T extends object> (object: T, setSignal: React.Dispatch<React.SetStateAction<number>>): [proxy: T, revoke: () => void] {
23-
const revocables: Array<() => void> = []
24-
22+
function proxyObject<T extends object> (object: T, update: () => void): T {
2523
for (const key in object) {
2624
const original = object[key as keyof typeof object]
25+
2726
if (isPlainObject(original)) {
28-
const [subproxy, subrevoke] = proxyObject(original, setSignal)
27+
const subproxy = proxyObject(original, update)
28+
2929
object[key as keyof typeof object] = subproxy as any
30-
revocables.push(() => {
31-
subrevoke()
32-
object[key as keyof typeof object] = original
33-
})
3430
}
3531
}
3632

37-
const proxy = Proxy.revocable(object, {
38-
set (target, prop, newValue) {
39-
if (prop !== 'valueOf' && target[prop as keyof typeof target] !== newValue) setSignal((prior) => prior + 1)
33+
const proxy = new Proxy(object, {
34+
set (target, prop, newValue, receiver) {
35+
if (prop !== 'valueOf' && target[prop as keyof typeof target] !== newValue) update()
36+
4037
const isPlain = isPlainObject(newValue)
4138
if (isPlain) {
42-
const [subproxy, subrevoke] = proxyObject(newValue, setSignal)
43-
revocables.push(() => {
44-
subrevoke()
45-
Reflect.set(target, prop, newValue)
46-
})
47-
return Reflect.set(target, prop, subproxy)
48-
} else return Reflect.set(target, prop, newValue)
39+
const subproxy = proxyObject(newValue, update)
40+
41+
return Reflect.set(target, prop, subproxy, receiver)
42+
} else return Reflect.set(target, prop, newValue, receiver)
4943
},
5044

5145
deleteProperty (target, prop) {
52-
if (prop in target) setSignal((prior) => prior + 1)
46+
if (prop in target) update()
47+
5348
return Reflect.deleteProperty(target, prop)
5449
}
5550
})
5651

57-
function revoke (): void {
58-
proxy.revoke()
59-
for (const subrevoke of revocables) subrevoke()
60-
}
61-
62-
return [proxy.proxy, revoke]
52+
return proxy
6353
}
6454

6555
/**
6656
* Create an object state value that auto updates on mutation \
6757
* This hook is recursive into simple object properties. Class instances will remain unaffected
6858
* @note Effects and memos that use this object should also listen for its signal: `+INSTANCE`
69-
* @warn You should revoke the proxy if you're done with render and don't want unforseen complications. Auto-revokes on and `setObject`
7059
* @param initial The initial object
71-
* @returns [object, setObject, forceUpdate, revoke]
60+
* @returns [object, setObject, forceUpdate]
7261
*/
73-
export function useObject<T extends object> (initial: T): [object: T, setObject: React.Dispatch<React.SetStateAction<T>>, forceUpdate: () => void, revoke: () => void] {
62+
export function useObject<T extends object> (initial: T): [object: T, setObject: React.Dispatch<React.SetStateAction<T>>, forceUpdate: () => void] {
7463
const revoked = useRef(false)
7564

7665
const [signal, setSignal] = useState(0)
7766
const [object, setObject] = useState(initial)
7867

79-
const [proxy, _revoke] = useMemo(() => proxyObject(object, setSignal), [object])
68+
const proxy = useMemo(() => proxyObject(object, () => setSignal((prior) => prior + 1)), [object, setSignal])
8069

81-
const forceUpdate = useCallback(() => {
70+
const forceUpdate = useCallback(() =>
8271
setSignal((prior) => prior + 1)
83-
}, [])
84-
85-
const revoke = useCallback(() => {
86-
if (!import.meta.hot) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
87-
_revoke()
88-
revoked.current = true
89-
}
90-
}, [_revoke])
72+
, [])
9173

9274
useEffect(() => {
93-
return () => revoke()
94-
}, [revoke])
75+
revoked.current = false
76+
return () => { revoked.current = true }
77+
}, [])
9578

9679
proxy.valueOf = () => signal
97-
return [revoked.current ? object : proxy, setObject, forceUpdate, revoke]
80+
return [revoked.current ? object : proxy, setObject, forceUpdate]
9881
}

0 commit comments

Comments
 (0)