Imagem com nome Redux

Gerenciamento de estado com Redux

Marcos Santos

--

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:

À esquerda é o problema da dificuldade de transmissão de estados, e à direita é a solução proposta pelo Redux. link da imagem: https://www.mrleo.dev/a-beginner's-guide-to-redux-with-react

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.

Fluxo redux: View, Action, Reducer, Store
imagem extraída de https://blog.novoda.com/introduction-to-redux-in-flutter/

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 o dispatch(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:

--

--