The Problem
Vue computed properties are cached based on their reactive dependencies. If a dependency changes in a way Vue cannot track, the computed property returns a stale cached value.
Symptoms
- Computed property shows old data even after source data changes
- Template displays cached computed value
- Works correctly when computed is changed to a method
- Only fails when the dependency is mutated indirectly
Real Error Scenario
```javascript const state = reactive({ user: { firstName: 'John', lastName: 'Doe' }, preferences: { format: 'upper' } });
const displayName = computed(() => {
const name = ${state.user.firstName} ${state.user.lastName};
return state.preferences.format === 'upper' ? name.toUpperCase() : name;
});
// Later, replacing the entire user object: state.user = { firstName: 'Jane', lastName: 'Smith' }; // displayName still shows "JOHN DOE" if not tracked properly! ```
How to Fix It
Fix 1: Ensure All Dependencies Are Accessed During Computation
const displayName = computed(() => {
// Access ALL reactive properties you depend on
const first = state.user.firstName;
const last = state.user.lastName;
const format = state.preferences.format;
const name = `${first} ${last}`;
return format === 'upper' ? name.toUpperCase() : name;
});Fix 2: Use Deep Reactivity with ref for Complex Objects
```javascript const user = ref({ firstName: 'John', lastName: 'Doe' }); const format = ref('upper');
const displayName = computed(() => {
const name = ${user.value.firstName} ${user.value.lastName};
return format.value === 'upper' ? name.toUpperCase() : name;
});
```
Fix 3: Force Recalculation with a Version Counter
```javascript const version = ref(0);
const displayName = computed(() => {
void version.value; // Force dependency on version
const name = ${state.user.firstName} ${state.user.lastName};
return state.preferences.format === 'upper' ? name.toUpperCase() : name;
});
function refreshDisplay() { version.value++; // Forces computed to recalculate } ```
Fix 4: Use a Method Instead of Computed
// When caching is actually the problem, use a method
function getDisplayName() {
const name = `${state.user.firstName} ${state.user.lastName}`;
return state.preferences.format === 'upper' ? name.toUpperCase() : name;
}In the template: {{ getDisplayName() }}
When Computed Caching Is Actually a Bug
If your computed depends on non-reactive data (like Date.now(), Math.random(), or external stores), Vue cannot track the dependency. Use a method or add a reactive version counter.