Chapter 104: Vue ‘renderTracked’ Lifecycle Hook
RenderTracked
This is not a hook you will use every day — or even every month. Most Vue developers never touch it in production code. But once you understand what it does, you will have a much deeper mental model of how Vue’s reactivity system actually works under the hood — and you will be able to debug very tricky performance issues that almost no one else can explain.
So let’s go slow, step by step, like I’m drawing the reactivity graph on the whiteboard.
1. What is renderTracked? (Very clear mental model)
renderTracked (and its sibling renderTriggered) are reactivity debugging hooks.
They let you observe exactly when Vue starts/stops tracking a reactive dependency during the render phase of your component.
In simple words:
Every time Vue renders your component (first mount + every update), it does this:
- Starts a new render tracking session
- Runs your render function / template
- Every time your template / render function reads a reactive value (ref.value, reactiveObj.prop, computed value…) → Vue tracks that value as a dependency
- When render finishes → Vue stops tracking and remembers: “These 17 refs/computeds were read → if any of them changes later → I must re-render this component”
renderTracked is called every single time Vue starts tracking a new reactive value during render.
renderTriggered is called every single time a tracked value actually changes and causes a re-render.
These two hooks are purely for debugging / profiling — they are not meant for production logic.
2. Signature & Arguments (what you actually get)
Composition API (what you use in <script setup>):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import { onRenderTracked, onRenderTriggered } from 'vue' onRenderTracked((event) => { console.log('Vue just started tracking a dependency during render:', event) }) onRenderTriggered((event) => { console.log('A tracked dependency changed → this component will re-render:', event) }) |
The event object has three very useful properties:
| Property | Type | What it tells you |
|---|---|---|
| target | object / ref / computed | The reactive object that was just read (reactiveObj, refImpl, computedRef) |
| key | string | symbol | Which property was accessed (‘count’, ‘user.name’, Symbol(‘value’) for ref.value) |
| type | string | What kind of operation happened: • ‘get’ (normal read) • ‘has’ • ‘iterate’ (for-in / Object.keys) |
3. Real Example – Seeing Exactly Which Dependencies Are Tracked
|
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 60 61 62 |
<template> <div class="demo"> <h2>renderTracked & renderTriggered Demo</h2> <p>Count A: {{ countA }}</p> <p>Count B: {{ countB }}</p> <p>Sum: {{ sum }}</p> <p>Double A: {{ doubleA }}</p> <button @click="countA++">+1 A</button> <button @click="countB++">+1 B</button> </div> </template> <script setup lang="ts"> import { ref, computed, onRenderTracked, onRenderTriggered } from 'vue' const countA = ref(5) const countB = ref(10) const sum = computed(() => { console.log('sum computed – reading A & B') return countA.value + countB.value }) const doubleA = computed(() => { console.log('doubleA computed – reading only A') return countA.value * 2 }) // ── Watch exactly which dependencies Vue tracks during render ── onRenderTracked((event) => { const targetType = event.target instanceof RefImpl ? 'ref' : event.target instanceof ReactiveEffect ? 'computed' : 'reactive object' console.group('renderTracked') console.log('→ Vue started tracking:') console.log(' target:', targetType, event.target) console.log(' key: ', event.key) console.log(' type: ', event.type) console.groupEnd() }) onRenderTriggered((event) => { console.group('renderTriggered') console.log('→ A tracked dependency changed → re-render scheduled') console.log(' target:', event.target) console.log(' key: ', event.key) console.log(' type: ', event.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 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 25 26 27 28 |
renderTracked → Vue started tracking: target: ref { value: 5 } key: value type: get renderTracked → Vue started tracking: target: computed { value: 15 } key: value type: get renderTracked → Vue started tracking: target: computed { value: 10 } key: value type: get renderTriggered → A tracked dependency changed → re-render scheduled target: ref { value: 6 } key: value type: set |
→ You see exactly which refs/computeds Vue tracked during render → When you change countA, Vue knows to re-run render because it previously tracked countA.value
4. Why renderTracked / renderTriggered are rarely used in production
They are debugging/profiling tools, not business logic hooks.
You use them when:
- You want to understand why a component re-renders too often
- You suspect unnecessary dependency tracking (wasted performance)
- You are optimizing a very performance-sensitive component (dashboard with 1000+ items, real-time feed…)
- You are writing Vue devtools plugins or advanced reactivity debugging tools
In normal application code → you almost never need them.
5. Quick Summary Table – renderTracked in 2026
| Question | Answer / Reality in 2026 |
|---|---|
| When does it run? | Every time Vue starts tracking a reactive dependency during render |
| Is it called on every render? | Yes — multiple times per render (once per tracked access) |
| Is DOM available? | No — runs during render phase, before DOM patch |
| Do modern developers use it? | Very rarely — mostly for debugging / profiling |
| Modern name | onRenderTracked & onRenderTriggered |
| Still asked in interviews? | Occasionally — to check deep understanding of reactivity |
| Typical real use | Find why component re-renders unnecessarily |
Pro Tips from Real Projects (Hyderabad 2026)
- Add onRenderTracked + onRenderTriggeredtemporarily when a component re-renders too often → log dependencies → find unnecessary reads
- Use Vue Devtools → Timeline first — it already shows re-render reasons; use these hooks only when you need more detail
- Never put business logic in these hooks — they run many times per render → performance killer
- In performance-critical components (virtual lists, real-time charts) → use these to prove which refs are causing re-renders
- Combine with Vue Devtools → Performance tab — see render time + which hooks run
Your mini homework:
- Create the example above
- Click “+1 A” multiple times → watch console logs → see exactly what Vue tracks
- Click “+1 B” → see that doubleA is not tracked → no unnecessary re-render
- Add a useless {{ someUnusedRef.value }} in template → see it tracked → understand waste
Any part confusing? Want full examples for:
- renderTracked + renderTriggered to debug over-re-rendering?
- Performance optimization workflow using these hooks?
- renderTracked in virtual list / large table scenario?
- Comparison with watch / watchEffect for debugging?
Just tell me — we’ll debug reactivity together step by step 🚀
