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, shift but not for arr[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'! } ```

vue
<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

javascript
function updateSecond() {
  items.value.splice(1, 1, 'blueberry'); // Triggers reactivity
}

Fix 2: Replace the Entire Array

javascript
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 ref over reactive for arrays
  • Use Vue DevTools to verify reactivity is tracking your changes