← Back to Design Systems and Frontend Team
See how it helps
2. Derived state with
Predictable Vue state updates
Organizes reactive state so the interface updates when expected, without duplicated values, looping watchers or abandoned background work.
vue-reactivity
Team members using this skill
When is it useful?
Use when a Vue view stops updating, recalculates too often or triggers repeated requests after a small change.
What does it help you do?
- Chooses appropriate reactive containers and keeps one authoritative owner for each value.
- Calculates derived values directly instead of synchronizing duplicate state through watchers.
- Limits watchers to real side effects and cleans up timers, listeners and pending work.
Try asking this
Fix a filter panel whose totals become stale and whose watchers trigger repeated requests. Derive totals from one source and clean up requests when filters change. Change two filters quickly and reset them together. Totals must derive from the latest state, with one intended request sequence and no watcher feedback loop.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Vue Reactivity & Composition API
Drive the UI from a clear, minimal reactive state graph: one authoritative source per state, pure computed derivations, and explicit side-effect watchers with cleanup.
1. Choosing reactive primitives
- Default to
ref()for primitives, arrays and objects whose whole value may be replaced. Use.valuein<script>and rely on top-level unwrapping in<template>. - Use
shallowRef()(orshallowReactive()) for large datasets, third-party instances (charts, editors, map SDKs) or immutable server payloads where deep tracking adds needless overhead. Trigger updates by replacing.valueor callingtriggerRef(). - If you use
reactive(), never reassign the variable (state = ...severs the reference) and never destructure its properties directly (const { count } = stateloses reactivity); usetoRef()ortoRefs(). - Refs inside
reactive({})unwrap automatically, but refs inside plain arrays (reactive([ref(1)])),Map/Set, or nested non-top-level template expressions still require.valueor acomputed.
2. Derived state with computed
- Derive every value that is a function of existing state with
computed()instead of storing a duplicaterefsynchronized in awatch. - Keep
computedgetters pure and synchronous: no network calls, no DOM mutations, no mutating other state, and no in-place array mutations (list.value.sort()or.reverse()mutates the source — copy first with[...list.value].sort()or.toSorted()).
3. Watchers and side effects
- Use
watchorwatchEffectonly for real side effects (fetching data, syncing DOM/storage, imperative third-party APIs), never to cascade state between local refs. - Choose the right watcher:
watch(source, cb): explicit dependencies, lazy by default, provides(newVal, oldVal). Pass a getter() => props.idwhen watching a reactive property; passingprops.iddirectly passes a raw value and fails to track.watchEffect(cb): runs immediately and tracks every reactive property read synchronously before the firstawait.
- Avoid
deep: trueon large objects when a targeted getter() => [form.status, form.assigneeId]suffices. - Clean up async or subscribed side effects when the source changes or the scope disposes: use
onWatcherCleanup(fn)(Vue 3.5+, called synchronously beforeawait) or theonCleanupparameter inwatch((_, __, onCleanup) => ...). - Use
watchPostEffect(flush: 'post') when the callback reads Vue-updated DOM geometry.
4. Lifecycle and resource cleanup
- Call lifecycle hooks (
onMounted,onUpdated,onUnmounted,onScopeDispose) synchronously inside<script setup>orsetup(), never after anawait. - Pair every
addEventListener,ResizeObserver,IntersectionObserver, timer (setInterval,setTimeout), WebSocket or store subscription with cleanup inonUnmounted/onScopeDispose.
Before you finish
- Every state has one primary owner; derived values use pure
computed(), not synced refs. - No lost reactivity from destructuring
reactive()or passing raw property values towatch(). - Watchers perform side effects only, avoid chained loops, and cancel stale work on re-run.
- Every listener, timer, observer and subscription is cleaned up on unmount or scope disposal.
Included files 2
LICENSE.txtSKILL.md
