Redux: o que é e como usá-lo em um projeto React

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?

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 de payload, 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.

Resultado React Redux

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.