Gerenciamento de estado é um dos maiores problemas em grande aplicações front-end. Em aplicações React, por exemplo, compartilhar informações entre componentes pode ser uma tarefa trabalhosa, caso esses componentes estejam aninhados em vários níveis. O Redux surge para nos ajudar a resolver esse problema, sendo uma solução robusta e eficaz para fazer o gerenciamento de estado de uma aplicação.
Confira, abaixo, o conteúdo disponibilizado:
- O que é Redux?
- Principais elementos do Redux
- Fluxo das informações no Redux
- Quando usar o Redux?
- React-redux
- Criando uma aplicação com Redux
O que é Redux?
De acordo com a própria documentação, o Redux é um padrão e uma biblioteca para gerenciamento e atualização de estado.
O Redux é uma biblioteca que pode ser utilizada com qualquer framework (como React, Vue e etc.), ou até mesmo com Javascript Vanilla (Javascript puro, sem nenhum framework).
Uma das vantagens do Redux é que ele mantém centralizado, não só o estado global, mas também a lógica que fará a atualização desse estado, fazendo com que sua aplicação tenha um comportamento mais consistente.
Principais elementos do Redux
Para utilizar o Redux em uma aplicação, é necessário seguir sua arquitetura, para que as informações do estado sejam lidas e atualizadas dentro do fluxo correto.
Vamos conhecer os principais elementos dessa arquitetura:
- Action: as actions descrevem eventos que aconteceram na aplicação. São representadas por objetos que contém as informações dos eventos disparados e, obrigatoriamente, precisam ter uma propriedade chamada
type
, que deve ser um texto que descreva a ação ocorrida. Também é possível que a action tenha outra propriedade, geralmente chamada depayload
, que irá conter alguma informação adicionar sobre o evento. É um padrão muito comum que, ao invés de criar um objeto literal, seja criada uma função que retorna um objeto. Essa função é chamada de “Action Creator”.
- Reducer: os reducers são funções responsáveis por alterar o estado da aplicação. Cada reducer funciona como se fosse um “event listener”, ou seja, ele fica “escutando” quando uma ação é disparada e, se for necessário, ele retorna um novo estado conforme as informações recebida pela action. A principal regra para os reducers é que eles precisam ser funções puras, ou seja, não podem gerar nenhum efeito colateral, como lógicas assíncronas, por exemplo.
- Store: é o local onde todo o estado fica armazenado, ou seja, é onde todas as informações da aplicação ficam centralizadas. A Store é responsável por gerenciar as atualizações do estado, através dos Reducers. Ela também fica responsável por disponibilizar o método
dispatch,
pelo qual as actions são chamadas.
Fluxo das informações no Redux
De maneira geral, o fluxo das informações funciona da seguinte forma no Redux:
1. Um componente da interface lê uma informação da Store e exibe na tela.
2. Algum componente gera uma interação com a pessoa usuária e dispara uma action.
3. A action disparada é “ouvida” por um reducer, que faz processamento necessário e atualiza o estado.
4. O componente inicial (do item 1) é atualizado com o novo estado e exibe a informação atualizada.
Quando usar o Redux?
Apesar de ser uma ferramenta eficaz no gerenciamento de estado, nem sempre o Redux é necessário em uma aplicação. A própria documentação recomenda o uso do Redux para aplicações que:
- possuem muitos estados que são compartilhados entre vários componentes;
- o estado da aplicação é atualizado frequentemente;
- precisem de uma lógica complexa para atualizar o estado;
- sejam mantidas por várias pessoas;
- precisem de um controle bastante rígido sobre as alterações do estado.
Por outro lado, como o Redux é uma ferramenta muito robusta, ela adiciona uma complexidade bastante grande na aplicação e, talvez, toda essa complexidade nem seja necessária.
Por isso, é importante ter em mente quais são os problemas que o Redux se propõe a resolver. Se você e seu time estão tendo dificuldades em compartilhar o estado de uma aplicação entre diversos componentes, então com certeza o Redux é uma boa opção.
React-redux
Como falado anteriormente, o Redux pode ser usado com vários frameworks front-end, com JavaScript Vanilla e também em aplicações mobile.
Apesar da versatilidade, a combinação mais comum é usar o React junto com o Redux. Isso acontece pois o Redux foi projetado pensando na forma como o React funciona.
E para ajudar na comunicação entre as duas ferramentas, foi desenvolvida uma biblioteca chamada react-redux
.
Um dos principais benefícios de usar essa biblioteca é que você não precisará preparar toda a comunicação entre o React e o Redux manualmente. A react-redux
possui métodos prontos para auxiliar nessa tarefa.
Além de ajudar na produtividade, já que você e seu time não terão que desenvolver esses métodos, a react-redux
também traz otimizações visando sempre a melhor performance da aplicação.
Criando uma aplicação com Redux
Vamos ver na prática como criar uma aplicação simples usando React e Redux, criando um contador de clicks, onde o estado será gerenciado pelo Redux.
1) Criando a aplicação React
Vamos usar o create-react-app
para criar uma nova aplicação React com o comando:
npx create-react-app redux-counter
2) Instalando o Redux e as dependências necessárias
Entre na pasta do projeto e instale as dependências que vamos usar nesse projeto:
npm install redux react-redux
3) Criando o componente Counter
Vamos criar um componente que será responsável por exibir o contador na tela.
// src/components/Counter.js
const Counter = () => {
return (
<div>
<p>0</p>
<button>Adicionar 1</button>
</div>
)
}
export default Counter;
E também vamos “limpar” o componente App.js
para que ele renderize somente o componente Counter
.
// src/App.js
import Counter from "./components/Counter";
function App() {
return (
<>
<Counter />
</>
);
}
export default App;
4) Criando a store
A primeira etapa para configurar o Redux em nossa aplicação é criar a store. Vamos criar uma nova pasta chamada store
e, dentro dela, criar um arquivo index.js
.
// src/store/index.js
import { createStore } from "redux";
const store = createStore(state => state);
export default store;
Após criar a store, vamos englobar nossa aplicação com o Provider
da biblioteca react-redux
, dessa forma, teremos acesso ao estado global em toda nossa aplicação. Vamos alterar o arquivo src/index.js
.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
5) Criando o reducer
O próximo passo é criar o reducer, que é a função responsável por alterar o estado. Vamos criar um novo arquivo na pasta store/reducer/counterReducer.js
.
// src/store/reducer/counterRedux.js
const INITIAL_STATE = {
counter: 0
}
const counterReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case "INCREMENT_COUNTER":
return {
...state,
counter: state.counter + 1
}
default:
return state;
}
}
export default counterReducer;
Com o reducer criado, precisamos adicioná-lo na store.
// src/store/index.js
import { createStore } from "redux";
import counterReducer from "./reducer/counterReducer";
const store = createStore(counterReducer);
export default store;
6) Criando a action
Agora que temos a store e o reducer, podemos criar nossa action, que será disparada quando quisermos incrementar o contador. Vamos criar um novo arquivo chamado src/store/actions/index.js
.
// src/store/actions/index.js
export const incrementCounter = () => (
{
type: "INCREMENT_COUNTER"
}
);
7) Lendo o estado e disparando a action dentro do componente Counter
Para ler as informações do estado, vamos usar o hook useSelector
. Para disparar a ação de incrementar o contador, vamos usar o hook useDispatch
, passando a action incrementCounter
que criamos no passo anterior.
// src/components/Counter.js
import { useSelector, useDispatch } from "react-redux";
import { incrementCounter } from "../store/actions";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector(state => state.counter);
return (
<div>
<p>{counter}</p>
<button
onClick={() => dispatch(incrementCounter())}
>
Adicionar 1
</button>
</div>
)
}
export default Counter;
Pronto! Agora temos o Redux configurado em nossa aplicação React. Basta clicar no botão “Adicionar 1” e verificar que o estado é atualizado na tela.
O Redux é uma ferramenta muito poderosa para gerenciar o estado global de uma aplicação. Além disso, se encaixa perfeitamente com a estrutura do React, sendo essa uma combinação muito valiosa e requisitada no mercado de trabalho.