Skip to content

Commit debd37d

Browse files
ygj6antfu
andauthored
fix(observe): solve the Ref not unwrapping on the ssr side issue with recursive way. (#723)
Co-authored-by: Anthony Fu <[email protected]>
1 parent df16c13 commit debd37d

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

src/reactivity/reactive.ts

+25-3
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,32 @@ export function observe<T>(obj: T): T {
127127

128128
// in SSR, there is no __ob__. Mock for reactivity check
129129
if (!hasOwn(observed, '__ob__')) {
130-
def(observed, '__ob__', mockObserver(observed))
130+
mockReactivityDeep(observed)
131131
}
132132

133133
return observed
134134
}
135135

136-
export function createObserver() {
137-
return observe<any>({}).__ob__
136+
/**
137+
* Mock __ob__ for object recursively
138+
*/
139+
function mockReactivityDeep(obj: any, seen = new WeakMap<any, boolean>()) {
140+
if (seen.has(obj)) return
141+
142+
def(obj, '__ob__', mockObserver(obj))
143+
seen.set(obj, true)
144+
145+
for (const key of Object.keys(obj)) {
146+
const value = obj[key]
147+
if (
148+
!(isPlainObject(value) || isArray(value)) ||
149+
isRaw(value) ||
150+
!Object.isExtensible(value)
151+
) {
152+
continue
153+
}
154+
mockReactivityDeep(value)
155+
}
138156
}
139157

140158
function mockObserver(value: any = {}): any {
@@ -149,6 +167,10 @@ function mockObserver(value: any = {}): any {
149167
}
150168
}
151169

170+
export function createObserver() {
171+
return observe<any>({}).__ob__
172+
}
173+
152174
export function shallowReactive<T extends object = any>(obj: T): T
153175
export function shallowReactive(obj: any): any {
154176
if (!isObject(obj)) {

src/reactivity/set.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ export function set<T>(target: AnyObject, key: any, val: T): T {
4141
return val
4242
}
4343
if (!ob) {
44-
// If we are using `set` we can assume that the unwrapping is intended
45-
defineAccessControl(target, key, val)
44+
target[key] = val
4645
return val
4746
}
4847
defineReactive(ob.value, key, val)

test/ssr/ssrReactive.spec.ts

+16
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,20 @@ describe('SSR Reactive', () => {
102102
new: true,
103103
})
104104
})
105+
106+
// #721
107+
it('should behave correctly for the nested ref in the object', () => {
108+
const state = { old: ref(false) }
109+
set(state, 'new', ref(true))
110+
expect(JSON.stringify(state)).toBe(
111+
'{"old":{"value":false},"new":{"value":true}}'
112+
)
113+
})
114+
115+
// #721
116+
it('should behave correctly for ref of object', () => {
117+
const state = ref({ old: ref(false) })
118+
set(state.value, 'new', ref(true))
119+
expect(JSON.stringify(state.value)).toBe('{"old":false,"new":true}')
120+
})
105121
})

0 commit comments

Comments
 (0)