Skip to content

Commit 82bdf86

Browse files
committed
fix(reactivity): ensure computed is invalidated before other effects
fix #5720
1 parent 56879e6 commit 82bdf86

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

packages/reactivity/__tests__/computed.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,23 @@ describe('reactivity/computed', () => {
170170
expect(dummy).toBe(-1)
171171
})
172172

173+
// #5720
174+
it('should invalidate before non-computed effects', () => {
175+
let plusOneValues: number[] = []
176+
const n = ref(0)
177+
const plusOne = computed(() => n.value + 1)
178+
effect(() => {
179+
n.value
180+
plusOneValues.push(plusOne.value)
181+
})
182+
// access plusOne, causing it to be non-dirty
183+
plusOne.value
184+
// mutate n
185+
n.value++
186+
// on the 2nd run, plusOne.value should have already updated.
187+
expect(plusOneValues).toMatchObject([1, 2, 2])
188+
})
189+
173190
it('should warn if trying to set a readonly computed', () => {
174191
const n = ref(1)
175192
const plusOne = computed(() => n.value + 1)

packages/reactivity/src/effect.ts

+25-10
Original file line numberDiff line numberDiff line change
@@ -348,16 +348,31 @@ export function triggerEffects(
348348
debuggerEventExtraInfo?: DebuggerEventExtraInfo
349349
) {
350350
// spread into array for stabilization
351-
for (const effect of isArray(dep) ? dep : [...dep]) {
352-
if (effect !== activeEffect || effect.allowRecurse) {
353-
if (__DEV__ && effect.onTrigger) {
354-
effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
355-
}
356-
if (effect.scheduler) {
357-
effect.scheduler()
358-
} else {
359-
effect.run()
360-
}
351+
const effects = isArray(dep) ? dep : [...dep]
352+
for (const effect of effects) {
353+
if (effect.computed) {
354+
triggerEffect(effect, debuggerEventExtraInfo)
355+
}
356+
}
357+
for (const effect of effects) {
358+
if (!effect.computed) {
359+
triggerEffect(effect, debuggerEventExtraInfo)
360+
}
361+
}
362+
}
363+
364+
function triggerEffect(
365+
effect: ReactiveEffect,
366+
debuggerEventExtraInfo?: DebuggerEventExtraInfo
367+
) {
368+
if (effect !== activeEffect || effect.allowRecurse) {
369+
if (__DEV__ && effect.onTrigger) {
370+
effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
371+
}
372+
if (effect.scheduler) {
373+
effect.scheduler()
374+
} else {
375+
effect.run()
361376
}
362377
}
363378
}

0 commit comments

Comments
 (0)