Skip to content
← Todas las preguntas
Avanzado

¿Cuándo usarías shallowRef / shallowReactive?

ReactividadRendimiento

Por defecto, ref y reactive hacen tus datos profundamente reactivos — Vue rastrea cada propiedad anidada, sin importar cuán profunda sea. Esto es conveniente pero tiene un coste: Vue recorre todo el árbol de objetos y envuelve cada objeto anidado en un Proxy. Para objetos pequeños está bien. Para una lista de 10.000 elementos, cada uno con propiedades anidadas, es trabajo desperdiciado si nunca editas elementos individuales en su lugar.

shallowRef y shallowReactive resuelven esto rastreando solo el primer nivel.

shallowRef: solo rastrea el reemplazo de .value

Un shallowRef dispara actualizaciones solo cuando reemplazas .value por completo. Las mutaciones a propiedades dentro del valor NO se rastrean.

ts
import { shallowRef, triggerRef } from 'vue'

const items = shallowRef<Item[]>([])

// ❌ Esto NO dispara un re-render
items.value.push(newItem)

// ✅ Reemplaza el valor completo — dispara la actualización
items.value = [...items.value, newItem]

// ✅ O muta y fuerza el trigger manualmente
items.value.push(newItem)
triggerRef(items)

shallowReactive: solo rastrea las propiedades raíz

Un shallowReactive rastrea adiciones, eliminaciones y cambios en las propiedades del primer nivel, pero no hace reactivos los objetos anidados.

ts
import { shallowReactive } from 'vue'

const state = shallowReactive({
  count: 0,
  nested: { deep: 'value' }
})

state.count++              // ✅ rastreado — propiedad raíz
state.nested = { deep: 1 } // ✅ rastreado — propiedad raíz reemplazada
state.nested.deep = 2      // ❌ NO rastreado — mutación anidada

Cuándo usarlos

Usa shallowRef cuando:

  • Recibes arrays grandes de una API que muestras pero no editas en línea (filas de tabla, resultados de búsqueda, entradas de log)
  • Almacenas objetos complejos con su propio estado interno que no necesitas que Vue rastree (instancias de clases de terceros, datos de gráficos, estado de canvas)
  • Siempre reemplazas el valor completo en lugar de mutar propiedades anidadas
ts
const chartData = shallowRef<ChartConfig>(initialConfig)

async function refresh() {
  const data = await fetchChartData()
  chartData.value = data // el reemplazo completo dispara la actualización
}

Usa shallowReactive cuando:

  • Tienes un objeto de configuración plano donde solo cambian las propiedades del primer nivel
  • Estás construyendo un formulario donde cada campo es un valor simple (no un objeto anidado)

Profundo vs superficial: la compensación

ref / reactiveshallowRef / shallowReactive
Qué se rastreaTodo, recursivamenteSolo el primer nivel
Coste de configuraciónMayor (envuelve cada objeto anidado)Menor
Estilo de mutaciónMuta cualquier cosa, en cualquier lugarReemplaza el valor del primer nivel o usa triggerRef
Cuándo usarPor defecto para la mayoría de datosConjuntos de datos grandes, objetos externos, rutas críticas de rendimiento

Empieza con ref/reactive. Solo cambia a variantes superficiales cuando midas un problema de rendimiento o cuando la reactividad profunda no tenga sentido para tus datos (como un contexto Canvas o una instancia WebSocket).

Ver también: ¿Cuándo usar markRaw y toRaw? · ¿Puede Object.freeze() reemplazar a markRaw?

Referencias

Publicado bajo la licencia MIT.