]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): re-run effect when is dirty in the pikax/computed_render_issue 10090/head
authorCarlos Rodrigues <carlos@hypermob.co.uk>
Fri, 12 Jan 2024 09:37:28 +0000 (09:37 +0000)
committerCarlos Rodrigues <carlos@hypermob.co.uk>
Fri, 12 Jan 2024 09:37:28 +0000 (09:37 +0000)
packages/reactivity/__tests__/computed.spec.ts
packages/reactivity/src/effect.ts

index f66935d4c8d29af78bb864406b4c73e648fc0cd3..546e466820cec3b7aa6577c3656fd513e5cee57a 100644 (file)
@@ -72,6 +72,21 @@ describe('reactivity/computed', () => {
     expect(c1.value).toBe(1)
   })
 
+  it('should work when chained(ref+computed)', () => {
+    const value = ref(0)
+    const provider = computed(() => value.value + consumer.value)
+    const consumer = computed(() => {
+      value.value++
+      return 'foo'
+    })
+    expect(provider.value).toBe('1foo')
+
+    value.value += 1
+    expect(provider.value).toBe('3foo')
+    value.value += 1
+    expect(provider.value).toBe('5foo')
+  })
+
   it('should trigger effect when chained', () => {
     const value = reactive({ foo: 0 })
     const getter1 = vi.fn(() => value.foo)
index 5ddf8e6f0accfd1c576fe37043f03807f772bd0f..1a92a739630d9318df201861922c3396577e2d18 100644 (file)
@@ -110,7 +110,12 @@ export class ReactiveEffect<T = any> {
       activeEffect = this
       this._runnings++
       preCleanupEffect(this)
-      return this.fn()
+      const r = this.fn()
+      // @ts-expect-error this has become dirty in the run
+      if (this._dirtyLevel === DirtyLevels.Dirty) {
+        return this.fn()
+      }
+      return r
     } finally {
       postCleanupEffect(this)
       this._runnings--
@@ -289,9 +294,17 @@ export function triggerEffects(
   debuggerEventExtraInfo?: DebuggerEventExtraInfo,
 ) {
   pauseScheduling()
+  const hasDepsRunning = activeEffect ? dep.has(activeEffect) : false
   for (const effect of dep.keys()) {
     if (!effect.allowRecurse && effect._runnings) {
-      continue
+      if (hasDepsRunning && effect !== activeEffect) {
+        // maybe this effect is actually recursive
+        if (effect.allowRecurse === undefined) {
+          effect.allowRecurse = true
+        }
+      } else {
+        continue
+      }
     }
     if (
       effect._dirtyLevel < dirtyLevel &&