Skip to content

Commit 0b23fd2

Browse files
authored
fix(reactivity): should not recompute if computed does not track reactive data (#12341)
close #12337
1 parent 8b848cb commit 0b23fd2

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

packages/reactivity/__tests__/computed.spec.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,17 @@ describe('reactivity/computed', () => {
10121012
expect(cValue.value).toBe(1)
10131013
})
10141014

1015+
test('should not recompute if computed does not track reactive data', async () => {
1016+
const spy = vi.fn()
1017+
const c1 = computed(() => spy())
1018+
1019+
c1.value
1020+
ref(0).value++ // update globalVersion
1021+
c1.value
1022+
1023+
expect(spy).toBeCalledTimes(1)
1024+
})
1025+
10151026
test('computed should remain live after losing all subscribers', () => {
10161027
const state = reactive({ a: 1 })
10171028
const p = computed(() => state.a + 1)

packages/reactivity/src/effect.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export enum EffectFlags {
4949
DIRTY = 1 << 4,
5050
ALLOW_RECURSE = 1 << 5,
5151
PAUSED = 1 << 6,
52+
EVALUATED = 1 << 7,
5253
}
5354

5455
/**
@@ -377,22 +378,22 @@ export function refreshComputed(computed: ComputedRefImpl): undefined {
377378
}
378379
computed.globalVersion = globalVersion
379380

380-
const dep = computed.dep
381-
computed.flags |= EffectFlags.RUNNING
382381
// In SSR there will be no render effect, so the computed has no subscriber
383382
// and therefore tracks no deps, thus we cannot rely on the dirty check.
384383
// Instead, computed always re-evaluate and relies on the globalVersion
385384
// fast path above for caching.
385+
// #12337 if computed has no deps (does not rely on any reactive data) and evaluated,
386+
// there is no need to re-evaluate.
386387
if (
387-
dep.version > 0 &&
388388
!computed.isSSR &&
389-
computed.deps &&
390-
!isDirty(computed)
389+
computed.flags & EffectFlags.EVALUATED &&
390+
((!computed.deps && !(computed as any)._dirty) || !isDirty(computed))
391391
) {
392-
computed.flags &= ~EffectFlags.RUNNING
393392
return
394393
}
394+
computed.flags |= EffectFlags.RUNNING
395395

396+
const dep = computed.dep
396397
const prevSub = activeSub
397398
const prevShouldTrack = shouldTrack
398399
activeSub = computed
@@ -402,6 +403,7 @@ export function refreshComputed(computed: ComputedRefImpl): undefined {
402403
prepareDeps(computed)
403404
const value = computed.fn(computed._value)
404405
if (dep.version === 0 || hasChanged(value, computed._value)) {
406+
computed.flags |= EffectFlags.EVALUATED
405407
computed._value = value
406408
dep.version++
407409
}

0 commit comments

Comments
 (0)