No pierdas la reactividad: cómo desestructurar reactive
Si en tus proyectos Vue trabajas con la Composition API (algo que te recomiendo), habrás utilizado reactive
para crear objetos reactivos. Por ejemplo, algo así:
const state = reactive({
online: true,
username: 'juanwmedia'
})
Ahora bien, ¿qué ocurre si quieres crear una referencia reactiva (con ref
) a una propiedad del objeto reactivo state
?.
Quizás pienses que puedes acceder a él sin más y mantener la reactividad:
const username = ref(state.username) // ❌ no es reactivo
Sin embargo, esto no será reactivo, ya que lo estaremos enviando a ref
es un valor primitivo (en este caso un string
), no la referencia al objeto reactivo que lo contiene.
toRef al rescate
Para poder crear una referencia reactiva a una propiedad de un objeto reactivo, Vue pone a nuestra disposición toRef
. Utilizarlo es muy sencillo:
const username = toRef(state, 'username') // ✅ es reactivo
Como ves, toRef
acepta dos argumentos. El primero es el objeto reactivo donde vive la propiedad que queremos referenciar. Por último, el identificador de la propiedad en sí.
Otro ejemplo típico donde es muy sencillo perder reactividad es trabajando con funciones compositoras, más conocidas como composables.
Supongamos que nuestro composable devuelve un objeto reactivo. Por ejemplo, las coordenadas del ratón:
export const useMouse = () => {
const coords = reactive({ x: 0, y: 0 });
function updateCoords({ pageX, pageY }) {
console.log(pageX, pageY);
coords.x = pageX;
coords.y = pageY;
}
onMounted(() => window.addEventListener('mousemove', updateCoords));
onUnmounted(() => window.removeEventListener('mousemove', updateCoords));
return coords; // 👁 retornamos un objeto reactivo
};
Cuando ejecutemos el composable, es muy tentador desestructurar el objeto resultante:
const { x, y } = useMouse(); // ❌ perdemos la reactividad
Sin embargo, recuerda, no estamos trabajando con un objeto plano sino con un reactivo (con Proxy). No podemos extraer un valor sin más y mantener la reactividad.
toRefs
Para solucionar el problema tenemos otra función llamada toRefs
, esta convierte un objeto reactivo en uno plano, donde cada propiedad es una referencia reactiva (creada con toRef
) a la propiedad original del objeto reactivo.
En nuestro ejemplo, podemos aplicar toRefs
en dos lugares. El primero es al hacer uso del composable.
const { x, y } = toRefs(useMouse()); // ✅ mantenemos la reactividad
O —más útil— retornar toRefs
desde el propio composable.
export const useMouse = () => {
...
return toRefs(coords);
};
Demo
¿Tienes alguna pregunta sobre No pierdas la reactividad: cómo desestructurar reactive?
Resuelve todas tus dudas sobre Vue en la Comunidad de Escuela Vue: un lugar donde participar, aprender y ayudar. ¡Te esperamos!.
Tras el registro (si no lo has hecho ya) serás redirigido/a al canal adecuado en la Comunidad.