No pierdas la reactividad: cómo desestructurar reactive

Inicial Vue Curso Vue en Escuela Vue

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

Código asociado
Curso Vue en Escuela Vue

¿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.

Twitter

Sigue el día a día y todo lo relacionado con Escuela Vue a través de su cuenta de Twitter.

Discord

En la Comunidad de Escuela Vue podrás solucionar tus dudas y ayudar a otras personas como tú a solucionar las suyas.

Recibe novedades en tu 📬