Chapter 105: Vue ‘renderTriggered’ Lifecycle Hook
RenderTriggered
(its modern Composition API name is onRenderTriggered)
Together with its sibling renderTracked / onRenderTracked, these two hooks form the deepest window into Vue’s reactivity system that you can get without writing your own custom reactivity debugger.
They are not business-logic hooks. They are purely observability tools — meant for developers who want to understand exactly why a component is re-rendering (and sometimes way too often).
In 2026, you will see these hooks almost exclusively in:
- performance optimization sessions
- debugging “why is this component re-rendering 200 times per second?”
- writing advanced devtools / profiling tools
- Vue core contributors or reactivity nerds
Most application developers never touch them in production code.
1. What exactly does renderTriggered tell you?
Every time Vue decides to re-render a component, it is because at least one reactive dependency that was read during the previous render has changed.
renderTriggered is called right when Vue detects such a change and schedules a re-render.
It gives you:
- Which reactive object was modified (target)
- Which exact property/key was set (key)
- What kind of operation happened (type: usually ‘set’, ‘add’, ‘delete’, etc.)
In other words:
“Hey developer, one of the things you read last time the component rendered just changed — that’s why I’m going to re-run the render function now.”
2. Signature & Arguments (what you actually receive)
Composition API (what you use in <script setup>):
|
0 1 2 3 4 5 6 7 8 9 10 |
import { onRenderTriggered } from 'vue' onRenderTriggered((event) => { console.log('renderTriggered – a dependency change triggered re-render:', event) }) |
The event object has three very useful properties:
| Property | Type | What it tells you |
|---|---|---|
| target | object / RefImpl / ComputedRef | The reactive object / ref / computed that was modified |
| key | string | symbol | Which property was changed (‘count’, ‘user.name’, Symbol(‘value’) for ref.value) |
| type | string | What happened to the property: • ‘set’ • ‘add’ • ‘delete’ • ‘clear’ |
3. Real Example – Seeing Exactly Which Change Causes Re-render
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<template> <div class="demo"> <h2>renderTriggered Demo – Why am I re-rendering?</h2> <p>Count A: {{ countA }}</p> <p>Count B: {{ countB }}</p> <p>Sum (computed): {{ sum }}</p> <p>Double A (computed): {{ doubleA }}</p> <button @click="countA++">+1 A (should trigger re-render)</button> <button @click="countB++">+1 B (should NOT trigger re-render)</button> <button @click="unusedProp++">Change unused value (should NOT trigger)</button> </div> </template> <script setup lang="ts"> import { ref, computed, onRenderTracked, onRenderTriggered } from 'vue' const countA = ref(5) const countB = ref(10) const unusedProp = ref(42) // we never read this in template const sum = computed(() => { console.log('sum computed – reading countA & countB') return countA.value + countB.value }) const doubleA = computed(() => { console.log('doubleA computed – reading only countA') return countA.value * 2 }) // ── Log every time Vue starts tracking something during render ── onRenderTracked((e) => { console.groupCollapsed('renderTracked – dependency read') console.log(' target:', e.target) console.log(' key: ', e.key) console.log(' type: ', e.type) console.groupEnd() }) // ── Log every time a tracked dependency changes → re-render scheduled ── onRenderTriggered((e) => { console.group('renderTriggered – re-render scheduled because:') console.log(' target:', e.target) console.log(' key: ', e.key) console.log(' type: ', e.type) console.groupEnd() }) </script> <style scoped> .demo { padding: 2rem; max-width: 600px; margin: 2rem auto; background: white; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); } </style> |
What you see in console when you interact:
Click “+1 A” multiple times:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
renderTracked – dependency read target: ref { value: 5 } key: value type: get renderTracked – dependency read target: computed { value: 15 } key: value type: get renderTracked – dependency read target: computed { value: 10 } key: value type: get renderTriggered – re-render scheduled because: target: ref { value: 6 } key: value type: set |
Click “+1 B” multiple times:
→ No renderTriggered log at all → Vue did not schedule a re-render — because countB was never read during previous render
Click “Change unused value” multiple times:
→ No renderTriggered → unusedProp is never read → changing it does nothing to the component
→ You just proved: Vue only re-renders when a previously-read reactive value changes
4. Why renderTriggered / renderTracked are rarely used in production
They are debugging / profiling tools, not business logic.
You use them when:
- A component is re-rendering far too often → you want to know which exact ref/property is causing it
- You suspect unnecessary dependency tracking (reading something you don’t actually need)
- You are optimizing a performance-critical component (real-time dashboard, virtual list, large table…)
- You are writing Vue devtools extensions, reactivity profilers, or teaching reactivity
In normal application code → you almost never need them.
5. Quick Summary Table – renderTriggered in 2026
| Question | Answer / Reality in 2026 |
|---|---|
| When does it run? | Every time a previously-tracked reactive value changes → re-render scheduled |
| How many times per change? | Once per triggering dependency (can be multiple if many changed) |
| Is DOM available? | No — runs during reactivity scheduling, before patch |
| Do modern developers use it? | Very rarely — only for deep debugging / optimization |
| Modern name | onRenderTriggered & onRenderTracked |
| Typical real use | Find why a component re-renders unnecessarily |
| Still asked in interviews? | Occasionally — to check deep understanding of reactivity |
Pro Tips from Real Projects (Hyderabad 2026)
- Add onRenderTriggeredtemporarily when a component re-renders too often → log the key & target → find the guilty ref/property
- Use Vue Devtools → Timeline first — it already shows re-render reasons; use these hooks only when you need finer-grained “which exact key” info
- Never put business logic in these hooks — they can run many times per second in hot code paths
- In performance-critical components (virtual lists, real-time charts, large forms) → use these to prove which refs are causing waste
- Combine with Vue Devtools → Performance tab — see render time + which hooks run + flame chart
Your mini homework:
- Create the example above
- Click “+1 A” → see renderTriggered for countA
- Click “+1 B” → see norenderTriggered (because countB was never read)
- Add a useless {{ unusedProp.value }} in template → click change button → now see renderTriggered for it
Any part confusing? Want full examples for:
- renderTriggered + renderTracked to debug over-re-rendering in a large list?
- Performance optimization workflow using these hooks?
- renderTriggered in virtual-scroller / infinite-load scenario?
- Comparison with watch / watchEffect for debugging?
Just tell me — we’ll debug reactivity together step by step 🚀
