Skip to content

Commit 154233a

Browse files
committedApr 13, 2022
fix(reactivity): fix ref tracking of self-stopping effects
close #5707
1 parent f4f5e80 commit 154233a

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed
 

‎packages/reactivity/__tests__/effect.spec.ts

+21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ref,
23
reactive,
34
effect,
45
stop,
@@ -801,6 +802,26 @@ describe('reactivity/effect', () => {
801802
expect(dummy).toBe(3)
802803
})
803804

805+
// #5707
806+
// when an effect completes its run, it should clear the tracking bits of
807+
// its tracked deps. However, if the effect stops itself, the deps list is
808+
// emptied so their bits are never cleared.
809+
it('edge case: self-stopping effect tracking ref', () => {
810+
const c = ref(true)
811+
const runner = effect(() => {
812+
// reference ref
813+
if (!c.value) {
814+
// stop itself while running
815+
stop(runner)
816+
}
817+
})
818+
// trigger run
819+
c.value = !c.value
820+
// should clear bits
821+
expect((c as any).dep.w).toBe(0)
822+
expect((c as any).dep.n).toBe(0)
823+
})
824+
804825
it('events: onStop', () => {
805826
const onStop = jest.fn()
806827
const runner = effect(() => {}, {

‎packages/reactivity/src/effect.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ export class ReactiveEffect<T = any> {
6464
* @internal
6565
*/
6666
allowRecurse?: boolean
67+
/**
68+
* @internal
69+
*/
70+
private deferStop?: boolean
6771

6872
onStop?: () => void
6973
// dev only
@@ -114,11 +118,18 @@ export class ReactiveEffect<T = any> {
114118
activeEffect = this.parent
115119
shouldTrack = lastShouldTrack
116120
this.parent = undefined
121+
122+
if (this.deferStop) {
123+
this.stop()
124+
}
117125
}
118126
}
119127

120128
stop() {
121-
if (this.active) {
129+
// stopped while running itself - defer the cleanup
130+
if (activeEffect === this) {
131+
this.deferStop = true
132+
} else if (this.active) {
122133
cleanupEffect(this)
123134
if (this.onStop) {
124135
this.onStop()

0 commit comments

Comments
 (0)
Please sign in to comment.