Skip to main content

Component re-rendering

1. Each component has its own "render effect"

When a component mounts, Vue creates a render function - the one that turns reactive data into a virtual DOM. This function is wrapped in a reactive effect (ReactiveEffect).

javascript
effect(() => { // render component template vnode = renderComponent() })

This effect works like an observer: when it runs, Vue remembers which reactive properties were "read" during the render.


2. Dependency tracking (track)

When the template uses, for example:

javascript
<p>{{ user.name }}</p>

On the first render, the following happens:

  1. Vue accesses user.name.
  2. This property is reactive, wrapped in a Proxy.
  3. The get trap inside the Proxy calls track(target, key).
  4. track() registers the dependency:
javascript
targetMap = WeakMap { user -> Map { name -> Set(effectRenderComponent) } }

Now Vue knows the component depends on user.name.


3. When the data changes (trigger)

When the value changes:

javascript
user.name = 'Alex'

Vue intercepts this through the set trap and calls:

javascript
trigger(user, 'name')

Now trigger():

  1. Finds all effects that depend on user.name (in our case, the component's render effect).
  2. Puts the effect in the update queue.

4. Updating only the components that need it

The queue can hold many effects, but Vue runs only the ones that depend on the changed property.

  • user.name changed -> only the component where it is used updates.
  • count changed -> only the component using count updates.
  • The rest of the components remain untouched.

This is granular reactivity: Vue does not do a "global re-render", it precisely updates only the branches of the component tree that need it.


5. How Vue avoids unnecessary re-renders

Vue 3 does this very smartly:

  • Components have update flags (dirty flags).
  • If the data has not changed (oldValue === newValue), no re-render happens.
  • Vue batches updates: all changes within one tick are combined and run asynchronously in the "microtask queue" (via Promise.resolve()).

This means that if 10 reactive properties change during a single event, Vue recalculates everything once, not 10 times.


6. Updates along the "reactive tree"

You can picture the dependency system as a reactive tree:

javascript
Reactive data (ref, reactive) └── Computed values └── Watchers / render effects └── ComponentsVirtual DOMReal DOM

When Vue calls trigger(), the update travels along a branch of the tree, not through the whole application. If the user.age property changes, Vue does not touch components that use user.name.


7. A simple explanation in plain words

When a component renders, Vue "listens" to which data it uses.

Then, when that data changes, Vue "calls" only the components that are subscribed to it.

Everything else is left untouched.


8. Quick summary

StageWhat happens
1. RenderThe component accesses reactive data -> Vue tracks dependencies via track()
2. Data changeThe Proxy calls trigger() for the changed properties
3. Finding effectsVue finds the components that depend on that data
4. Update queueEffects land in the queue (batch updates)
5. Re-renderOnly the necessary components re-render

9. Visual analogy

javascript
Component "UserCard" ├── depends on user.name └── depends on user.age Component "PostCard" └── depends on post.title user.name changed -> only UserCard re-renders

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.