--- title: VNodes Must Be Unique in Render Functions impact: HIGH impactDescription: Reusing vnode references causes rendering bugs and unexpected behavior type: gotcha tags: [vue3, render-function, vnode, composition-api] --- # VNodes Must Be Unique in Render Functions **Impact: HIGH** - Reusing the same vnode reference multiple times in a render function tree causes rendering bugs, where only one instance appears or updates behave unexpectedly. Every vnode in a component's render tree must be unique. You cannot use the same vnode object multiple times. If you need to render the same element multiple times, create each vnode separately using a factory function or by calling `h()` in a loop. ## Task Checklist - [ ] Never store a vnode in a variable and use it multiple times in the same tree - [ ] Use a factory function or `.map()` to create multiple similar vnodes - [ ] Each `h()` call creates a new vnode, so call it for each instance needed - [ ] Be especially careful when extracting vnode creation into helper functions **Incorrect:** ```javascript import { h } from 'vue' export default { setup() { return () => { // WRONG: Same vnode reference used twice const p = h('p', 'Hello') return h('div', [p, p]) // Bug! Duplicate vnode reference } } } ``` ```javascript import { h } from 'vue' export default { setup() { return () => { // WRONG: Reusing vnode in different parts of tree const icon = h('span', { class: 'icon' }, '★') return h('div', [ h('button', [icon, ' Save']), // Uses icon h('button', [icon, ' Delete']) // Reuses same icon - Bug! ]) } } } ``` **Correct:** ```javascript import { h } from 'vue' export default { setup() { return () => { // CORRECT: Create new vnode for each use return h('div', [ h('p', 'Hello'), h('p', 'Hello') ]) } } } ``` ```javascript import { h } from 'vue' export default { setup() { return () => { // CORRECT: Factory function creates new vnode each time const createIcon = () => h('span', { class: 'icon' }, '★') return h('div', [ h('button', [createIcon(), ' Save']), h('button', [createIcon(), ' Delete']) ]) } } } ``` ```javascript import { h } from 'vue' export default { setup() { return () => { // CORRECT: Using map to create multiple vnodes return h('div', Array.from({ length: 20 }).map(() => h('p', 'Hello')) ) } } } ``` ```javascript import { h } from 'vue' export default { setup() { const items = ['Apple', 'Banana', 'Cherry'] return () => h('ul', // CORRECT: Each iteration creates a new vnode items.map((item, index) => h('li', { key: index }, item) ) ) } } ``` ## Why VNodes Must Be Unique VNodes are lightweight JavaScript objects that Vue's virtual DOM algorithm uses for diffing and patching. When the same vnode reference appears multiple times: - Vue cannot differentiate between the instances - The diffing algorithm produces incorrect results - Only one instance may render, or updates may corrupt the DOM Each vnode maintains its own identity and position in the tree, which is essential for: - Correct DOM patching during updates - Proper lifecycle hook execution - Accurate key-based reconciliation in lists ## Reference - [Vue.js Render Functions - Vnodes Must Be Unique](https://vuejs.org/guide/extras/render-function.html#vnodes-must-be-unique)