fix(watch): cleanup watcher effect from scope when manually stopped (#9978)

This commit is contained in:
Yang Mingshan 2024-01-04 10:36:13 +08:00 committed by GitHub
parent f70f7ca9ae
commit d2d89551bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 2 deletions

View File

@ -1443,4 +1443,35 @@ describe('api: watch', () => {
expect(spy1).toHaveBeenCalledTimes(1) expect(spy1).toHaveBeenCalledTimes(1)
expect(spy2).toHaveBeenCalledTimes(1) expect(spy2).toHaveBeenCalledTimes(1)
}) })
test("effect should be removed from scope's effects after it is stopped", () => {
const num = ref(0)
let unwatch: () => void
let instance: ComponentInternalInstance
const Comp = {
setup() {
instance = getCurrentInstance()!
unwatch = watch(num, () => {
console.log(num.value)
})
return () => null
},
}
const root = nodeOps.createElement('div')
createApp(Comp).mount(root)
expect(instance!.scope.effects.length).toBe(2)
unwatch!()
expect(instance!.scope.effects.length).toBe(1)
const scope = effectScope()
scope.run(() => {
unwatch = watch(num, () => {
console.log(num.value)
})
})
expect(scope.effects.length).toBe(1)
unwatch!()
expect(scope.effects.length).toBe(0)
})
}) })

View File

@ -5,6 +5,7 @@ import {
ReactiveEffect, ReactiveEffect,
ReactiveFlags, ReactiveFlags,
type Ref, type Ref,
getCurrentScope,
isReactive, isReactive,
isRef, isRef,
isShallow, isShallow,
@ -394,10 +395,11 @@ function doWatch(
const effect = new ReactiveEffect(getter, NOOP, scheduler) const effect = new ReactiveEffect(getter, NOOP, scheduler)
const scope = getCurrentScope()
const unwatch = () => { const unwatch = () => {
effect.stop() effect.stop()
if (instance && instance.scope) { if (scope) {
remove(instance.scope.effects!, effect) remove(scope.effects, effect)
} }
} }