diff --git a/packages/runtime-core/__tests__/rendererComponent.spec.ts b/packages/runtime-core/__tests__/rendererComponent.spec.ts index c389e1e8354..3fdc388823d 100644 --- a/packages/runtime-core/__tests__/rendererComponent.spec.ts +++ b/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(`

0

`) + expect(spy).toHaveBeenCalledTimes(1) + + text.value++ + await nextTick() + expect(serializeInner(root)).toBe(`

1

`) + expect(spy).toHaveBeenCalledTimes(2) + }) }) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 17eaaf44d5c..76848cb52f3 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/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