Parcourir la source

fix(runtime-core): fix child component double update on props change

fix #4365
Evan You il y a 4 ans
Parent
commit
c1f564e1dc

+ 30 - 0
packages/runtime-core/__tests__/rendererComponent.spec.ts

@@ -324,4 +324,34 @@ describe('renderer: component', () => {
     expect(serializeInner(root)).toBe(``)
     expect(ids).toEqual([ids[0], ids[0] + 1, ids[0] + 2])
   })
+
+  test('child component props update should not lead to double update', async () => {
+    const text = ref(0)
+    const spy = jest.fn()
+
+    const App = {
+      render() {
+        return h(Comp, { text: text.value })
+      }
+    }
+
+    const Comp = {
+      props: ['text'],
+      render(this: any) {
+        spy()
+        return h('h1', this.text)
+      }
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(App), root)
+
+    expect(serializeInner(root)).toBe(`<h1>0</h1>`)
+    expect(spy).toHaveBeenCalledTimes(1)
+
+    text.value++
+    await nextTick()
+    expect(serializeInner(root)).toBe(`<h1>1</h1>`)
+    expect(spy).toHaveBeenCalledTimes(2)
+  })
 })

+ 4 - 2
packages/runtime-core/src/renderer.ts

@@ -1458,6 +1458,9 @@ function baseCreateRenderer(
           pushWarningContext(next || instance.vnode)
         }
 
+        // Disallow component effect recursion during pre-lifecycle hooks.
+        effect.allowRecurse = false
+
         if (next) {
           next.el = vnode.el
           updateComponentPreRender(instance, next, optimized)
@@ -1465,8 +1468,6 @@ function baseCreateRenderer(
           next = vnode
         }
 
-        // Disallow component effect recursion during pre-lifecycle hooks.
-        effect.allowRecurse = false
         // beforeUpdate hook
         if (bu) {
           invokeArrayFns(bu)
@@ -1481,6 +1482,7 @@ function baseCreateRenderer(
         ) {
           instance.emit('hook:beforeUpdate')
         }
+
         effect.allowRecurse = true
 
         // render