Skip to content

Commit

Permalink
fix(reactivity): ensure watch(Effect) can run independent of unmounte…
Browse files Browse the repository at this point in the history
…d 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
LinusBorg authored Jan 9, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 8731852 commit cd7c887
Showing 2 changed files with 44 additions and 2 deletions.
40 changes: 40 additions & 0 deletions packages/runtime-core/__tests__/apiWatch.spec.ts
Original file line number Diff line number Diff line change
@@ -1150,4 +1150,44 @@ describe('api: watch', () => {
// own update effect
expect(instance!.scope.effects.length).toBe(1)
})

test('watchEffect should keep running if created in a detatched scope', async () => {
const trigger = ref(0)
let countWE = 0
let countW = 0
const Comp = {
setup() {
effectScope(true).run(() => {
watchEffect(
() => {
trigger.value
countWE++
},
)
watch(
trigger,
() => countW++
)
})
return () => ''
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
// only watchEffect as ran so far
expect(countWE).toBe(1)
expect(countW).toBe(0)
trigger.value++
await nextTick()
// both watchers run while component is mounted
expect(countWE).toBe(2)
expect(countW).toBe(1)
render(null, root) // unmount
await nextTick()
trigger.value++
await nextTick()
// both watchers run again event though component has been unmounted
expect(countWE).toBe(3)
expect(countW).toBe(2)
})
})
6 changes: 4 additions & 2 deletions packages/runtime-core/src/apiWatch.ts
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@ import {
isReactive,
ReactiveFlags,
EffectScheduler,
DebuggerOptions
DebuggerOptions,
getCurrentScope,
} from '@vue/reactivity'
import { SchedulerJob, queueJob } from './scheduler'
import {
@@ -197,7 +198,8 @@ function doWatch(
)
}

const instance = currentInstance
const instance = getCurrentScope() === currentInstance?.scope ? currentInstance : null
// const instance = currentInstance
let getter: () => any
let forceTrigger = false
let isMultiSource = false

0 comments on commit cd7c887

Please sign in to comment.