Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Vue Source State, Computed Views, and Large Snapshots

Last updated: 5 Oct 20268 min read
tutorial
IntermediateBy AITrove Editorial

A Vue ref or reactive object represents state whose changes can trigger dependent work. A computed value derives a result from the reactive values it reads and caches that result until those dependencies change. This makes it a good home for a filtered queue or count, but not for an asynchronous request or an impure mutation. Storing source cases, filtered cases, and count as three independently writable values creates a synchronization problem that the framework cannot solve automatically. Reactivity also has a cost. Deeply tracking every property of a very large, immutable server snapshot adds proxy work that may bring no benefit if updates always replace the whole snapshot. The choice is not between reactive and nonreactive everything; it is to make each ownership and update boundary explicit.

Working case

A permit dashboard receives a 47,000-case search snapshot. Its component keeps a mutable array, a second filtered array, and a separate count. A watcher copies the filtered data after each phrase change, and a later watcher updates the count. The UI occasionally displays 62 visible cases beside 81 rows when a replacement snapshot arrives between the two updates. The team retains one server snapshot and one search phrase, then derives filtered cases and count from the same computed result. Because the snapshot is replaced as a unit, the team evaluates shallow storage for the large immutable collection; they do not silently mutate one nested case in place and expect that shallow storage to report it.

Implementation boundary

javascript
import { computed, shallowRef, ref } from "vue";

export function usePermitSearch(initialCases) {
  const caseSnapshot = shallowRef(initialCases);
  const phrase = ref("");
  const visibleCases = computed(() => {
    const needle = phrase.value.trim().toLocaleLowerCase();
    return caseSnapshot.value.filter((permitCase) => permitCase.title.toLocaleLowerCase().includes(needle));
  });
  const visibleCount = computed(() => visibleCases.value.length);
  function replaceSnapshot(nextCases) { caseSnapshot.value = nextCases; }
  return { phrase, visibleCases, visibleCount, replaceSnapshot };
}

Inventory which values are authoritative: the server snapshot, phrase, selected case ID, and pending operation. Put the source values in refs and compute filtered rows from snapshot plus phrase. Compute count from those rows rather than running a second filter. Keep the computed getter pure: no network request, log submission, or state write. If a snapshot contains tens of thousands of immutable objects and every update replaces it, a shallow ref can avoid deep conversion overhead. That choice requires immutable replacement when a record changes; document it in the data layer and test it. If individual nested fields are edited in place, a deeply reactive structure may be appropriate, though it has tracking cost. Measure both update frequency and filtering cost before introducing indexes, worker computation, or windowed rendering. A method that reads current reactive state on every render may be fine for cheap work; a computed value is especially useful when the same expensive result has several consumers.

Cost and boundaries

Filtering all 47,000 records is O(n) per invalidation and stores a result array of up to O(n) references. Computed caching avoids rerunning when its reactive dependencies stay unchanged; it does not make a changed search phrase free. A shallow ref reduces nested tracking but requires O(n) or targeted structural copying for immutable replacements, depending on the data shape. An index adds memory and maintenance work; a worker adds transfer or sharing costs. A count stored independently uses little memory but risks correctness drift. Measure update-to-visible time, dependency invalidation frequency, and heap retention on a modest device rather than choosing a strategy from row count alone.

Failure trace

Replace the server snapshot while a phrase is active and assert rows and count agree in one render. Change a case status through the documented replacement path and verify the computed result updates. Mutate a nested object under shallow storage as a deliberate negative test; the absence of an update should reveal the contract breach. Type a phrase that matches nothing, clear it, and switch to a new snapshot without resetting the input. Profile a 47,000-row update and distinguish filter computation from DOM rendering. Confirm that reading the computed value twice without changed dependencies does not duplicate the filter work.

Verification

  • Visible rows and count derive from one source snapshot.
  • A shallow snapshot changes through replacement, not nested mutation.
  • Filtering and DOM rendering costs are measured separately.

Practice drill

Create 47 permit records first, then expand to 47,000. Keep one server snapshot and one search phrase. Derive visible cases and count, then make two UI consumers read the same computed result. Replace case 62 with a new object and record whether the view changes. Compare a deep ref and a shallow ref using the same immutable replacement flow. Measure filter time and rendered row count separately. State when an index or windowed list becomes necessary, and record the memory overhead of each choice.

Decision note

Store authoritative inputs once; derive views from them, and choose shallow tracking only with immutable replacement discipline.

Common Mistakes

  • Keeping derived rows and count as separately writable state.
  • Doing network work inside a computed getter.
  • Mutating a nested record in a shallow ref and expecting notification.

Related lessons

Vue Reactivity and Component Boundaries; Vue Watch Cleanup and Stale Request Ownership; Vue Props, Emits, and Keyed Editor Ownership; Vue Server Rendering and Hydration Stability; Application Search and Retrieval; Browser Performance Diagnosis and Measurement.

Apply and check

Build Project: Vue permit review queue and review Web Development: Vue reactivity and boundaries quiz.

web-tech
web-development
Storage details