Gerenciamento de estado com Redux
Neste post vou estar descrevendo de forma simples o que é e como podemos gerenciar estados com o Redux.
A finalidade deste post, é ajudar, você que esta iniciando com o Redux, de uma forma simples começar a criar e gerenciar seus estados.
Afinal oque é o Redux ?
O Redux é um container de estado previsível para aplicativos JavaScript, uma biblioteca criada por Dan Abramov. Ele é baseado em uma implementação de uma arquitetura, criada pelo Facebook, chamada flux.
Por mais popular que o Redux seja por seu uso junto ao React, ele pode ser utilizado com qualquer outra biblioteca de visualizações, Vue, Angular ou com seu framework javascript favorito.
Temos muitos não é verdade..
Como citado na documentação do redux: Ele ajuda a escrever aplicativos que se comportam de maneira consistente, e podem ser executados em diferentes ambientes(cliente, servidor e nativo) e são fáceis de testar.
O seu objetivo é melhorar o compartilhamento de estado entre componentes, como ilustrado na imagem abaixo:
Ao invés de mantermos o estado por componente, o Redux nos possibilita gerenciar um estado global dos componentes chamado Store.
Mas como gerenciamos este fluxo deste Store ?
Como o Redux foi desenvolvido em cima da arquitetura flux, o fluxo de dados tem muito em comum. Se você é novo e não conhece o flux, fique tranquilo, não é nada de outro planeta.
Para realizar tal fluxo, dividimos a configuração do Redux em 4 partes:
View: A view é um exemplo de visualização, onde o cliente pode interagir com a aplicação através de botões, inputs, etc.
A View é opcional na configuração do Redux, neste post o utilizaremos sem configurar a View.
Actions: A actions no redux são objetos de informações que enviam dados da sua aplicação para sua store. Em resumo as ações representam os fatos sobre “o que aconteceu”
Reducers: Os reducers especificam como o estado do aplicativo é alterado de acordo com às ações, ou seja recebem e tratam as informações para que sejam ou não enviadas à store.
Store: O store é responsavel pelo estado da aplicação e reúne as actions e os reducers. O redux diferentemente do flux, nos permite ter apenas uma store, uma unica fonte de verdade, assim centralizando nosso estado.
Vamos entender como isso funciona na prática ?
Antes de iniciar nosso exemplo, vou estar citando os passos que fiz caso queira testar você mesmo.
Crie um diretório com o nome que desejar, e dentro dele devemos baixar o pacote Redux:
Para fazer o download do redux podemos utilizar o npm ou o yarn, gerenciadores de pacotes.
Siga o comando abaixo para instalar o redux:
Para npm:
npm install -D redux
Para Yarn:
yarn add -D redux
Com o pacote instalado, já temos todo o necessário para iniciar.
Para que possamos abordar de forma mais clara o fluxo do redux, usarei um exemplo simples de contador.
Nosso usuário ira interagir com a aplicação de contador, através de duas ações, incrementar e decrementar.
Tudo pronto ? Vamos começar!
Em um aquivo “.js” importe o pacote do redux.
const Redux = require("redux");
Definindo nossas ações:
A ações devem ter uma propriedade
type
que indique o tipo de ação que está sendo executada. Os tipos normalmente devem ser definidos como constantes de string, para possibilitar uma fácil manutenção em uma aplicação de grande porte.
Exemplo:
const INCREMENT = 'INCREMENT'{ type: INCREMENT }
Vamos criar as ações de incrementar e decrementar do nosso contador. Podemos transformar nossas actions em simples métodos, chamados actions creators, fazendo a action ser portável e fácil de testar.
// contants
const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'// Actions creators
const increment = (value = 1) => ({
type: INCREMENT,
payload: value
})const decrement = (value = 1) => ({
type: DECREMENT,
payload: value
})
Em seguida definimos nosso reducer:
O reducer é uma função pura, que recebe o estado atual, a action e retornam o estado modificado de acordo com a action, seu comportamento, é exatamente como a função reduce no javascript
(state, action) => state
Vamos definir um reducer chamado contador, podemos iniciar o estado com um objeto auxiliar, o declarei como initialState, e a propriedade counter iniciando com 0.
const initialState = {
counter: 0
}// Reducer
const contador = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return {
counter: state.counter + action.payload
}
case DECREMENT:
return {
counter: state.counter - action.payload
}
default:
return state
}
}
Definimos que nossa action é composta por um type e um payload que carrega o valor que a ação deve estar emitindo como alteração para o estado. Caso a ação não seja encontrada o estado é retornado sem nenhuma alteração.
Definimos o store da aplicação.
Reforçando, aplicações redux o store possuem uma unica Store, e podemos cria-la da seguinte forma:
const Redux = require('redux')
const store = Redux.createStore(reducer)
Um store recebe apenas um reducer, mas como ele é apenas uma função podemos combinar vários redutores em um da maneira que quisermos, utilizando o método combineReducers()
. Mas este é assunto para um próximo post.
Já que estamos por dentro de como definir um reducer, vamos definir o nosso Store do contador.
const store = Redux.createStore(contador)
Abaixo podemos conferir nossas configurações todas juntas:
const Redux = require("redux");// contants
const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'// Actions
const increment = (value = 1) => ({
type: INCREMENT,
payload: value
})const decrement = (value = 1) => ({
type: DECREMENT,
payload: value
})// Reducer
const initialState = {
counter: 0
}const reducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return {
counter: state.counter + action.payload
}
case DECREMENT:
return {
counter: state.counter - action.payload
}
default:
return state
}
}// store
const store = Redux.createStore(reducer)
Mas como alteramos o store e obtemos os dados ?
A store possui 3 métodos internos:
Neste post utilizaremos o
getState()
que permite acesso ao estado e odispatch(action)
que permite que o estado seja atualizado ao emitir um ação.
Vamos criar um método chamado logState que utilizaremos para retornar nosso estado enquanto o modificamos:
const logState = () => store.getState()
E para disparar uma ação, informamos o action creator para que deve alterar o estado do contador, como parâmetro, do metodo dispatch
.
store.dispatch(<actionCreator>)
Como mostrado abaixo:
/** retorna o estado antes de qualquer ação */
const logState = () => store.getState()// Loga do estado antes das ações
console.log(logState()) // Resultado: { counter: 0 }// Dispara a ação incrementa com o valor de 5
store.dispatch(increment(5))
console.log(logState()) // Resultado: { counter: 5 }// Dispara a ação decrement com valor de 1
store.dispatch(decrement())
console.log(logState()) // Resultado: { counter: 4 }
Chegamos ao fim deste post, espero ter tirado suas duvidas e contribuído com seu aprendizado, até o próxima.
Referencias: