@@ -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