The Problem
Vue's reactivity system cannot detect direct array index assignment. When you write arr[2] = newValue, Vue does not know the array changed and the DOM does not update.
Symptoms
- Array data changes in JavaScript but the template still shows old values
- Console log shows the correct array, but the UI is stale
- Works for
push,pop,shiftbut not forarr[i] = x - Vue DevTools shows the array updated but the view did not re-render
Real Error Scenario
```javascript // Vue 3 Composition API const items = ref(['apple', 'banana', 'cherry']);
function updateSecond() { items.value[1] = 'blueberry'; // NOT REACTIVE! console.log(items.value); // ['apple', 'blueberry', 'cherry'] - looks correct // But template still shows 'banana'! } ```
<template>
<ul>
<li v-for="item in items" :key="item">{{ item }}</li>
</ul>
<!-- Still shows: apple, banana, cherry -->
</template>Why This Happens
Vue wraps arrays with reactive proxies. Direct index assignment bypasses the proxy trap because JavaScript's arr[index] = value does not trigger Vue's change detection for arrays.
How to Fix It
Fix 1: Use Array.splice
function updateSecond() {
items.value.splice(1, 1, 'blueberry'); // Triggers reactivity
}Fix 2: Replace the Entire Array
function updateSecond() {
items.value = [...items.value];
items.value[1] = 'blueberry';
// OR in one line:
items.value = items.value.map((item, i) => i === 1 ? 'blueberry' : item);
}Fix 3: Use Vue.set (Vue 2 Only)
```javascript import { set } from 'vue';
function updateSecond() { set(items, 1, 'blueberry'); // Vue 2 only } ```
Note: Vue 3's ref with .value handles this differently. Use Fix 1 or 2 for Vue 3.
Fix 4: For Nested Objects in Arrays
```javascript const users = ref([ { id: 1, name: 'Alice', active: false }, { id: 2, name: 'Bob', active: true } ]);
function toggleUser(index) { // WRONG: users.value[index].active = !users.value[index].active // For deeply nested changes, Vue 3 ref DOES detect property changes // But replacing the object is safer: users.value[index] = { ...users.value[index], active: !users.value[index].active }; // Then trigger array reactivity: items.value = [...items.value]; } ```
Prevention
- Never use direct index assignment on reactive arrays
- Use
splice(),map(), or spread to create new arrays - In Vue 3, prefer
refoverreactivefor arrays - Use Vue DevTools to verify reactivity is tracking your changes