Skip to content

Commit fbc0c42

Browse files
fix(reactivity): ensure watcher with once: true are properly removed from effect scope (#11665)
1 parent f2ea25d commit fbc0c42

File tree

2 files changed

+15
-10
lines changed

2 files changed

+15
-10
lines changed

packages/reactivity/src/watch.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -206,18 +206,26 @@ export function watch(
206206
getter = () => traverse(baseGetter(), depth)
207207
}
208208

209+
const scope = getCurrentScope()
210+
const watchHandle: WatchHandle = () => {
211+
effect.stop()
212+
if (scope) {
213+
remove(scope.effects, effect)
214+
}
215+
}
216+
209217
if (once) {
210218
if (cb) {
211219
const _cb = cb
212220
cb = (...args) => {
213221
_cb(...args)
214-
effect.stop()
222+
watchHandle()
215223
}
216224
} else {
217225
const _getter = getter
218226
getter = () => {
219227
_getter()
220-
effect.stop()
228+
watchHandle()
221229
}
222230
}
223231
}
@@ -317,14 +325,6 @@ export function watch(
317325
effect.run()
318326
}
319327

320-
const scope = getCurrentScope()
321-
const watchHandle: WatchHandle = () => {
322-
effect.stop()
323-
if (scope) {
324-
remove(scope.effects, effect)
325-
}
326-
}
327-
328328
watchHandle.pause = effect.pause.bind(effect)
329329
watchHandle.resume = effect.resume.bind(effect)
330330
watchHandle.stop = watchHandle

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

+5
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,11 @@ describe('api: watch', () => {
17711771
expect(scope.effects.length).toBe(1)
17721772
unwatch!()
17731773
expect(scope.effects.length).toBe(0)
1774+
1775+
scope.run(() => {
1776+
watch(num, () => {}, { once: true, immediate: true })
1777+
})
1778+
expect(scope.effects.length).toBe(0)
17741779
})
17751780

17761781
// simplified case of VueUse syncRef

0 commit comments

Comments
 (0)