diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index e4a337cb8b6..2eb683cdf64 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -1037,4 +1037,22 @@ describe('reactivity/computed', () => { state.a++ expect(pp.value).toBe(2) }) + + test('computed value updates correctly after dep cleanup', () => { + const obj = reactive({ foo: 1, flag: 1 }) + const c1 = computed(() => obj.foo) + + let foo + effect(() => { + foo = obj.flag ? (obj.foo, c1.value) : 0 + }) + expect(foo).toBe(1) + + obj.flag = 0 + expect(foo).toBe(0) + + obj.foo = 2 + obj.flag = 1 + expect(foo).toBe(2) + }) }) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 20bbada505f..82a82981f3c 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -321,7 +321,7 @@ function cleanupDeps(sub: Subscriber, fromComputed = false) { sub.depsTail = tail } -function isDirty(sub: Subscriber): boolean { +function isDirty(sub: Subscriber, isComputed = false): boolean { for (let link = sub.deps; link; link = link.nextDep) { if ( link.dep.version !== link.version || @@ -331,6 +331,14 @@ function isDirty(sub: Subscriber): boolean { ) { return true } + + if ( + isComputed && + link.dep.map && + link.dep.map.get(link.dep.key) !== link.dep + ) { + return true + } } // @ts-expect-error only for backwards compatibility where libs manually set // this flag - e.g. Pinia's testing module @@ -370,7 +378,7 @@ export function refreshComputed(computed: ComputedRefImpl): undefined { dep.version > 0 && !computed.isSSR && computed.deps && - !isDirty(computed) + !isDirty(computed, true) ) { computed.flags &= ~EffectFlags.RUNNING return