Redux: Um tutorial prático e simples!

Boa tarde a todos! Você está bem?

Com este post, pretendo envolver aqueles que estão começando com Redux e focar apenas no básico, usando uma implementação mínima para que funcione. Eu recomendo o básico de React, JSX, ES6+ e alguma terminologia de programação funcional.

O que é o Redux?

Redux é um contêiner baseado em Flux para controlar e gerenciar o estado global de aplicativos JavaScript (projetado para resolver o problema de compartilhamento de estado entre componentes, tornando-o unidirecional).

le foi criado por Dan Abramov e Andrew Clark em 2015 para resolver o problema de compartilhamento e acionamento de eventos entre componentes de aplicativos.

Redux é uma solução para compartilhamento de estado entre diversos componentes, tornando-o muito simples, previsível e rápido.

Seu uso é muito comum no React, que é uma biblioteca muito popular (ou framework, ainda há discussão sobre isso) para construção de interfaces, pois essa biblioteca foi criada com ReactJs em mente, mas também funciona com Angular e Vue.

Aplicativos sem Redux são forçados a acionar eventos entre vários componentes, tornando-os fortemente acoplados e dificultando a manutenção do projeto, pois um componente pode depender de vários outros para funcionar.

O diagrama abaixo é uma boa ilustração dos problemas e soluções fornecidas pelo redux.

Conceitos principais do Redux

Redux tem três conceitos principais: lojas, redutores e ações.

Store

É um container imutável, ou seja, não há mudança nele, mas evolução, e armazena e centraliza o estado global da aplicação. Com isso, podemos dizer que é um conjunto de estado de aplicação centralizado/agregado em um só lugar.

A Store segue um dos princípios que moldaram e definiram o conceito de Redux: um único ponto de verdade.

Os outros são:

Imutabilidade de estado: o estado do aplicativo é imutável, mas pode evoluir.

As alterações são realizadas apenas por funções puras: os redutores recebem ações emitidas aplicando-as ao estado global. sempre retorna um status.

Tecnicamente, é um objeto JavaScript que contém todo o estado dos componentes do aplicativo. Além disso, a loja tem a capacidade de monitorar mudanças e notificar quem precisa saber.

Reducers

Os redutores são funções puras (funções que não produzem efeitos colaterais, ou seja, para a mesma entrada temos a mesma saída), têm a capacidade de disparar eventos e podem alterar as propriedades armazenadas, evoluindo assim o estado global da aplicação.

Eles atuam como filtros que recebem e processam informações, enviando essas informações para a loja. Ele é responsável por lidar com todas as operações, como algum componente solicitando a alteração de alguns dados no armazenamento.

Para todos os dados contidos no armazenamento, deve haver um redutor próprio para esses dados.

Tecnicamente, um redutor é uma função JavaScript que recebe um estado anterior, ou um estado definido por um esquema e uma ação em seus argumentos, e dependendo do tipo dessa ação, pode gerar um novo estado, o que significa que não haverá sempre ser evolução stateful.

Então, dentro do redutor, temos ações.

Cada redutor ouvirá todas as ações acionadas pelo aplicativo e alterará qualquer informação de estado, precisamos usar redutores.

Anatomia de um reducer

const initialState = {...}

function exemploReducer1(state = initialState, action) {

switch(action.type) {

case ‘TYPE_1’ :

return { ...state, data: action.payload.data };

default:

return state;

                }

}

Actions

Estas são as fontes de informação que o redutor envia da aplicação para a loja. Eles são acionados (despachados) pelo criador da ação (a função pura responsável por criar a ação). Ainda falaremos mais sobre criadores de ação.

Tecnicamente, uma ação é um objeto que deve ter uma propriedade chamada tipo para indicar qual ação é. Pode ou não ter dados relevantes, mas geralmente tem. Esses dados são coletados em um único atributo chamado carga útil.

Como mencionado acima, a carga útil é um conjunto de dados, mas também pode ser, por exemplo, uma chamada para um back-end.

As ações não alteram nosso estado global. Lembre-se, eles são apenas objetos.

Anatomia da Action



    type: “TIPO_DO_EVENTO”,

    payload: {

// dados associados a essa action

         }

}

Action Creator

Actions creators são funções puras responsáveis por criarem as actions.

function func1(params) {

      // lógica




return {

type: “TIPO_EVENTO”,

payload: {

                          // dados associados a essa action 

                                  }

                           }

}

Estado (estado compartilhado)

Basicamente, é um objeto JavaScript com uma estrutura chave/valor.

{

atributo1: [ {...}, {...}, … ],

atributo2: {...}

}

Lembre-se de que o estado é gerado a partir de funções.

Conectar componentes ao Redux

Para acessar a evolução do estado da loja e disparar eventos para evoluí-la, você precisa se conectar/assinar o Redux. Como podemos fazer isso?

Basicamente são duas etapas:

1º passo: as importações.

import { bindActionCreators } from ‘redux’

import { connect } from ‘react-redux’

// e se você tiver um arquivos de actions creators, importe também.

Agora, seja um componente baseado em classe ou baseado em função, o final do arquivo deve ficar assim:

2º  passo : Conexão.

const mapDispatchToProps = (dispatch) => bindActionCreators({…}, dispatch );

export default connect(null, mapDispatchToProps)( //nome do componente);

Está bem até agora? vamos continuar……Agora que temos uma pequena ideia da teoria, vamos começar com um projeto bem simples, incluindo sua criação, instalação das dependências necessárias e uso.

Criar um projeto com Redux

Para criar um projeto, precisamos instalar o create-react-app globalmente. Para fazer isso, execute o comando abaixo se você não o tiver.

npm i -g create-react-app

Agora, crie qualquer pasta, abra o terminal/cmd e execute o comando abaixo, escolhendo o nome do projeto de exemplo.

npx create-react-app [nome do projeto]

Instalar dependências

Para usar redux em seu projeto, precisamos instalá-lo. Podemos fazer isso usando o gerenciador de pacotes npm ou yarn.

NPM

npm install –save redux react-redux

Yarn

yarn add redux react-redux

Nesse sentido, a dependência “extra” é para fazer a conexão do React com o Redux.

Começando a utilização (configuração)

Crie uma pasta chamada storeConfig dentro de src do seu projeto. Dentro da pasta, crie um arquivo chamado store.js. O código escrito nele pode ser:

import { createStore, combineReducers } from ‘redux’

const reducers = combineReducers({

prop1: function(state, action) {

return {

                   exemplo: “Deu certo!’

                   }

},




prop2: function(state, action) {

return {

exemplo: “De novo, deu certo!”

}

})




function store() {

return createStore(reducers)

}


export default store

A função combinar Redutores, como o nome sugere, combina todos os redutores do aplicativo para criar a loja. Para o nosso exemplo, temos dois redutores, mas em projetos React esse número costuma ser bem maior.

Em breve vamos envolver a criação da loja em uma função store através da função createStore (do Redux) e exportá-la.

Agora precisamos integrar o React com o Redux.

No arquivo index.js da sua aplicação, as importações podem ser mais ou menos como abaixo:

import { Provider } from ‘react-redux’

import storeConfig from ‘./storeConfig/store’




const store = storeConfig()

Nesse arquivo, teremos algo assim:




ReactDOM.render(

<React.StrictMode>

<App />

</React.StrictMode>,

document.getElementById(‘app’)

);

Agora ficará assim:




ReactDOM.render(

<Provider store={store}>

<React.StrictMode>

<App />

</React.StrictMode>

</Provider>,

document.getElementById(‘app’)

);

Pronto! Já temos a integração do React com Redux na sua aplicação. Agora, o que está faltando?

Como vincular componentes ao estado do aplicativo

Para isso, precisamos de um componente que esteja interessado em armazenar dados. Dentro da pasta src do seu projeto, crie uma pasta chamada components. Uma vez feito, crie um arquivo exampleComponent.jsx nessa pasta. Pode ser qualquer nome que você quiser, e pode fazer coisas realmente interessantes para você.

Coloque o código abaixo no arquivo jsx criado:

import React, { Fragment } from ‘react’

import { connect } from ‘react-redux’

function exemplo(props) {

return ( 

<Fragment>

<div> props.prop1.exemplo</div>

<div> props.prop2.exemplo</div>

</Fragment>

)

}




function mapStateToProps(state) {

return {

prop1: state.prop1,

prop2.state.prop2

}

}

export default connect(mapStateToProps)(exemplo)

Portanto, usamos connect (de react-redux) para retornar os componentes conectados, bem como o estado global do aplicativo. Ele é responsável por conectar nossos componentes ao estado global do aplicativo.

A função mapStateToProps mapeia o estado para as propriedades do componente.

Prontinho! Veja o que já temos:

Projeto criado.

Dependências instaladas.

Store criada.

Componente conectado.

Conclusão

O uso do Redux torna o gerenciamento de estado do seu aplicativo simples e extensível, facilitando a manutenção, pois o acoplamento entre os componentes é drasticamente reduzido, o que melhora coisas como a produtividade.

Redux tornou-se uma solução quase indispensável em aplicações React simplesmente porque resolve alguns problemas complexos de uma forma tão elegante.

Nota: ainda nem todos os aplicativos React requerem Redux. Realmente depende do grau de comunicação entre os componentes do aplicativo.

Por outro lado, a análise é necessária para entender quais estados devem realmente existir na Loja.

Back To Top