Przeglądaj źródła

fix(reactivity): re-run effect when is dirty in the

Carlos Rodrigues 2 lat temu
rodzic
commit
2c22cb38b0

+ 15 - 0
packages/reactivity/__tests__/computed.spec.ts

@@ -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)

+ 15 - 2
packages/reactivity/src/effect.ts

@@ -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 &&