Voltar

O que são os composables?

O que são os composables?

Composition API

Desde que o Evan You anunciou a Composition API muitos devs estavam empolgados e outros confusos e outros simplesmente não aceitavam a ideia.

Mas acontece que a Composition API veio e agora todos estão felizes com a facilidade que ela traz no desenvolvimento principalmente de grandes aplicações com Vue.

Quem conhece o meio React vai ver uma semelhança da Composition API do Vue com os Custom Hooks do React. Mas no Vue tem algumas diferenças que melhoram a experiência de desenvolvimento.

Para ajudar, a ideia da Composition API é podermos separar funcionalidades do componente em funções que simplesmente podem ser importadas. Assim temos um grande poder de reutilização de código trazendo assim a possibilidade de compor um componente conforme vamos importando as funções e usamos no componente.

Composable

E quando separamos essas funcionalidades em funções, damos o nome para cada função de composable.

Por definição, as funções composable tem um padrão no nome que é use<Funcionalidade>, por exemplo, useMouse.

Quando escrever um?

Até aqui tudo certo, então já podemos sair escrevendo composables e dando nome de useFazQualquerCoisa?!

Bem... Não. a proposta dos composables é trabalhar exclusivamente com a Composition API para gerenciar estados para o componente. O que quero dizer com isso?!

Vejamos o seguinte exemplo.

Temos a necessidade de sempre formatar uma string de data, podemos então criar uma função que faça isso correto?

formatDate.ts
export default function formatDate(date: Date) {
  const formatted = '';
  ...
  return formatted;
};

Inicialmente, pensamos: "Vou transformar em um composable chamado useFormatDate e reutilizar onde quiser"

export default function useFormatDate() {
  const formatDate = (date: Date) => {
    const formatted = '';
    ...
    return formatted;
  }

  return formatDate;
};

Assim posso usar nos componentes como um composable

<script setup lang="ts">
import useFormatDate from './composables/useFormatDate';

const formatDate = useFormatDate();
</script>

<template>
  <div>{{ formatDate(new Date()) }}</div>
</template>

Qual o problema nisso?

Bem, é que a ideia por trás dos composables é que eles usem a Composition API e no nosso exemplo, useFormatDate não faz uso de nenhuma função da Composition API, ou seja, não gerencia estado algum e se torna uma função sem estado. É assim que algumas libs funcionam como date-fns e lodash. Portanto, o ideal é que ela seja apenas uma função que ficaria ali no diretório helpers, utils ou qualquer outro. Mas ela não seria considerada uma função composable.

Vamos ver um outro exemplo então que faria mais sentido ser um composable.

Supomos que queremos sempre obter a posição do mouse para exibir na tela. Então teríamos:

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const x = ref(0)
const y = ref(0)

function update(event) {
  x.value = event.pageX
  y.value = event.pageY
}

onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

Se nós precisarmos utilizar essa lógica em outros componentes então faz sentido transformar em um composable. Já que temos um gerenciamento de estado.

// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// by convention, composable function names start with "use"
export default function useMouse() {
  // state encapsulated and managed by the composable
  const x = ref(0)
  const y = ref(0)

  // a composable can update its managed state over time.
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // a composable can also hook into its owner component's
  // lifecycle to setup and teardown side effects.
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // expose managed state as return value
  return { x, y }
}

Agora nos nossos componentes, basta chamar o composable

<script setup>
import useMouse from './composables/mouse.js'

const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

Percebeu o que fizemos? A ideia do composable é ter funções que isolam o gerenciamento de estado e que podem ser reutilizadas em outros componentes. Observe que o gerenciamento do estado é feito com a Composition API.


Exemplos tirados da documentação sobre composables