Reatividade turbinada com Vuex

Bruno Gaignoux
casasbahiatech
Published in
6 min readOct 22, 2020

Você já se perguntou para que serve o gerenciamento de estados em uma aplicação de frontend? Ou talvez tenha se perguntado como funciona esse gerenciamento?

Não é de hoje que muitas pessoas se perguntam porque e para que usamos o gerenciamento de estado em aplicações, quando o próprio framework já nos proporciona sua própria reatividade.

Antes de mais nada, precisamos falar sobre reatividade para entender o conceito do Vuex mais a fundo. Então vamos lá.

Reatividade

Esse tema não é algo novo no meio da comunidade, mas é um assunto um tanto quanto complexo, porque requer o conhecimento prévio de design patterns ou simplesmente muita fome de aprendizado.

O Vue possui um sistema de reatividade que quando é passado um objeto para o atributo data da sua instância, ele percorre as propriedades criando getters/setters usando o Object.defineProperty.

Toda diretiva ou data binding, será um objeto watcher que guardará as propriedades durante a avaliação de dependências, o que for coletado no getter. No momento em que o setter for chamado, o objeto irá reavaliar as dependências, o que acarretará no update da view.

Caso queiram saber detalhadamente como funciona esse processo de reatividade no vuejs, clica aqui pra saber mais.

Vuex

E o que seria o vuex? Segundo o seu próprio site, ele é um padrão de gerenciamento de estado combinado com uma biblioteca para aplicativos Vue.js que serve como um store centralizado para todos os componentes em uma aplicação, com regras que garantem que o estado só possa ser modificado de forma previsível.

Mas afinal, o que é um gerenciamento de estados?

Bom, pra começar a entender isso, vamos a um exemplo da documentação do Vuex que ajuda a explicar melhor:

new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})

O exemplo acima mostra como comumente criamos um aplicativo que é constituído das seguintes estruturas:

  • O estado (state), que é a fonte da verdade que direciona nosso aplicativo;
  • A view, que é apenas um mapeamento declarativo do estado;
  • As ações (actions), que são as possíveis maneiras pelas quais o estado pode mudar em reação às interações dos usuários da view.

Pra melhorar o entendimento desses conceitos, vamos de gráfico (one-way):

conceito “fluxo de dados unidirecional”

Tudo bem até aqui? Então vamos ao problema dessa implementação acima:

The Problemaum

Ainda segundo a documentação do Vuex, o problema dessa simplicidade é que ela passa a ser quebrada rapidamente quando temos vários componentes que compartilham um estado comum. Por exemplo:

  • Múltiplas views podem depender do mesmo pedaço de estado.
  • Ações de diferentes views podem precisar mudar o mesmo pedaço de estado.

Ambos os problemas citados acima, giram em torno de algo em comum, o mesmo estado para N componentes espalhados pelo sistema. Até podemos ficar passando propriedades por componentes várias e várias vezes, mas isso pode ser super entediante para componentes profundamente aninhados e simplesmente não funcionam para componentes irmãos, por exemplo. E frequentemente nos encontramos recorrendo a soluções como alcançar referências diretas da instância pai/filho ou tentar alterar e sincronizar várias cópias do estado por meio de eventos (eu já usei muito isso rs). Ambos os padrões são frágeis e levam rapidamente a um código muito complexo e de difícil manutenção.

Por esse motivo, o Vuex vem pra nos ajudar a compartilhar o estado entre os componentes, dessa forma o sistema como um todo se torna uma grande “view”, e qualquer componente tem o direito de acessar o estado ou acionar ações, não importando onde elas estejam na árvore! Não é muito legal?

Além disso, podemos dar ao nosso código mais estrutura e sustentabilidade dessa forma — até porque ninguém merece um código que só quem fez sabe mexer, não é mesmo?

Brincadeiras a parte, esta é a ideia básica por trás do Vuex, inspirada no Flux, Redux e The Elm Architecture. Ao contrário dos outros padrões, o Vuex também é uma implementação de biblioteca adaptada especificamente para o Vue.js tirar proveito de seu sistema de reatividade granular para atualizações eficientes.

Abaixo explico em forma de gráfico, o ciclo de vida do vuex:

Ciclo de vida Vuex

Na prática

E como seria toda essa boa e velha teoria aplicada na prática? Vamos imaginar o seguinte cenário:

  • Você possui uma aplicação que precisa do mesmo dado de clientes em 4 telas diferentes, na gestão de usuários, no cadastro de uma venda, na criação de despesa pessoal e na geração de relatório customizado. Você pode fazer 4 requisições para o banco de dados sem medo, mas com o Vuex, você basicamente precisaria somente de uma ou duas requisições no banco de dados para buscar as informações desses usuários cadastrados.

Logo, você só precisaria criar uma estrutura preparada para armazenar os códigos de ação, mutação e estado do módulo que você deseja, como o abaixo:

Estrutura modular do vuex

Após isso, você somente precisa criar uma função de ação para consumir os dados de usuários. Digamos que ao logar no seu sistema e, dessa forma, ela irá manipular o estado da variável do módulo referente a listagem de usuários e, a partir disso, em qualquer tela poderá ser acessado.

Por exemplo:

  • Arquivo actions.js
import axios from '@/server';export default {
getUsers({commit}) {
return new Promise((resolve, reject) => {
axios
.get('/Usuario/ListarUsuarios')
.then(response => {
commit('SET_USERS', response.data.rows);
resolve(response);
})
.catch(error => {
reject(error);
});
});
}
}
  • Arquivo mutations.js
export default {
SET_USERS(state, data) {
state.items = data;
},
};
  • Arquivo state.js
export default {
items: [],
};

E dessa forma, após o login ocorrer, nossa home irá buscar os dados dessa forma:

<script>
export default {
methods: {
ifLoginIsTrue() {
this.$store.dispatch('user/getUsers')
.catch(error => {
this.$loading.stop();
this.alert = {
show: true,
type: 'error',
message: error
};
});
},
},
};
</script>

E em qualquer tela podemos acessar a partir da expressão this.$store.state.user.items. Exemplo:

  • Componente de gestão de usuários
<template>
<div>
<v-data-table
class="elevation-1 mt-4"
:items="$store.state.user.items"
item-key="Nome"
/>
</div>
</template>

Reatividade turbinada

O termo turbinado está sendo usado nesse artigo para tentar exemplificar o uso da reatividade atrelado a mutação de estado que ocorre usando o Vuex. Dessa forma, podemos ter controle maior a partir do devTools do Vue, que nos traz um recurso bem legal chamado “time travel debugging” (algo como uma “volta”) que nos proporciona uma visão ampla dos estados anteriores da nossa aplicação. Como a imagem abaixo nos mostra:

Vue DevTool — Chrome

Conclusão

Por fim, quando podemos usar o Vuex?

Embora o Vuex nos ajude a lidar com o gerenciamento de estado compartilhado, ele também vem com o custo de mais conceitos e códigos repetitivos. É uma escolha de prós e contras entre produtividade de curto e longo prazo

Se você nunca construiu um SPA em grande escala e for direto para o Vuex, ele pode parecer detalhado e desanimador. Isso é perfeitamente normal se o seu aplicativo é simples, você provavelmente ficará bem sem o Vuex. Um simples store pattern pode ser tudo que você precisa. Mas, se você está criando um SPA de médio a grande porte, é provável que tenha encontrado situações que fazem você pensar em como lidar melhor com o estado fora de seus componentes do Vue, e o Vuex será o próximo passo natural para você.

Há uma boa citação de Dan Abramov, o autor do Redux:

As bibliotecas Flux são como óculos: você saberá quando precisar delas.

--

--

Bruno Gaignoux
casasbahiatech

Bacharel em Sistemas de Informação, Especialista em Engenharia de Software, Pós em Arquitetura e Design de Software e Aspirante a Músico.