Skip to content

Commit cd7c887

Browse files
authoredJan 9, 2023
fix(reactivity): ensure watch(Effect) can run independent of unmounted instance if created in a detatched effectScope (fix #7319) (#7330)
* fix(reactivity): ensure watch(Effect) can run independent of unmounted instance if created in a detatched effectScope * test: use separate counters for each watcher to make test more robust
1 parent 8731852 commit cd7c887

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed
 

‎packages/runtime-core/__tests__/apiWatch.spec.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1150,4 +1150,44 @@ describe('api: watch', () => {
11501150
// own update effect
11511151
expect(instance!.scope.effects.length).toBe(1)
11521152
})
1153+
1154+
test('watchEffect should keep running if created in a detatched scope', async () => {
1155+
const trigger = ref(0)
1156+
let countWE = 0
1157+
let countW = 0
1158+
const Comp = {
1159+
setup() {
1160+
effectScope(true).run(() => {
1161+
watchEffect(
1162+
() => {
1163+
trigger.value
1164+
countWE++
1165+
},
1166+
)
1167+
watch(
1168+
trigger,
1169+
() => countW++
1170+
)
1171+
})
1172+
return () => ''
1173+
}
1174+
}
1175+
const root = nodeOps.createElement('div')
1176+
render(h(Comp), root)
1177+
// only watchEffect as ran so far
1178+
expect(countWE).toBe(1)
1179+
expect(countW).toBe(0)
1180+
trigger.value++
1181+
await nextTick()
1182+
// both watchers run while component is mounted
1183+
expect(countWE).toBe(2)
1184+
expect(countW).toBe(1)
1185+
render(null, root) // unmount
1186+
await nextTick()
1187+
trigger.value++
1188+
await nextTick()
1189+
// both watchers run again event though component has been unmounted
1190+
expect(countWE).toBe(3)
1191+
expect(countW).toBe(2)
1192+
})
11531193
})

‎packages/runtime-core/src/apiWatch.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
isReactive,
88
ReactiveFlags,
99
EffectScheduler,
10-
DebuggerOptions
10+
DebuggerOptions,
11+
getCurrentScope,
1112
} from '@vue/reactivity'
1213
import { SchedulerJob, queueJob } from './scheduler'
1314
import {
@@ -197,7 +198,8 @@ function doWatch(
197198
)
198199
}
199200

200-
const instance = currentInstance
201+
const instance = getCurrentScope() === currentInstance?.scope ? currentInstance : null
202+
// const instance = currentInstance
201203
let getter: () => any
202204
let forceTrigger = false
203205
let isMultiSource = false

0 commit comments

Comments
 (0)
Please sign in to comment.