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
  • Loading branch information
LinusBorg committed Jan 9, 2023
1 parent 8731852 commit cd7c887
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
40 changes: 40 additions & 0 deletions packages/runtime-core/__tests__/apiWatch.spec.ts
Expand Up @@ -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
Expand Up @@ -7,7 +7,8 @@ import {
isReactive,
ReactiveFlags,
EffectScheduler,
DebuggerOptions
DebuggerOptions,
getCurrentScope,
} from '@vue/reactivity'
import { SchedulerJob, queueJob } from './scheduler'
import {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit cd7c887

Please sign in to comment.