React Redux vs Context APIReact Hooks.

Edgar Quintero
MCTW_TDW

--

Ao criar um projeto em React.Js queremos que o código desenvolvido seja simples e adequado às nossas necessidades. Nesse processo é inevitável sentirmos uma grande preocupação com a informação que iremos apresentar aos nossos utilizadores, principalmente em identificar a forma como vamos gerir e partilhar por todos os componentes da nossa aplicação.

Para gerir da melhor forma os estados da nossa aplicação, devemos conhecer as ferramentas disponíveis, as suas características principais, e o impacto que a sua utilização terá no nosso projeto. Neste artigo poderás encontrar uma breve apresentação das três formas mais utilizadas para partilhar informação entre componentes, React Redux, Context API e React Hooks, dando destaque ao enquadramento que irá permitir que identifiques qual a mais adequada em função das características do teu projeto.

React Redux

Figura 1: Estatísticas de utilização do React Redux

O React Redux é uma das bibliotecas mais usadas em JavaScript para a gestão de informação em aplicações de React.JS. Criada em 2015 por Dan Abramov e Andrew Clark tem como objetivo centralizar a gestão dos estados para que sejam facilmente partilhados por todos os componentes do teu projeto. Redux contém ferramentas para disponibilizar os dados da tua aplicação a nível global, simplificando a tarefa de passar dados entre “pais” e “filhos”, ou componentes “irmãos”.

Redux é principalmente útil quando falamos de grandes projetos, com inúmeros componentes onde todos eles precisam de consumir dados. Para ser eficiente e possuir esta característica global, a informação deve ser guardada numa Store, que serve como base provedora. Todos os outros componentes da aplicação contidos dentro deste componente “Pai”, terão acesso aos dados para os replicar e manipular.

Para isto, o Redux utiliza três conceitos fundamentais:

  • Store: É o lugar para guardar os estados de uma aplicação, por norma é aqui que se encontram os Reducers para gerir a informação de um projeto grande e complexo.
  • Reducers: Manipulam os estados da Store para retornar novos estados em função das Actions com as quais interagem.
  • Actions: Estas ações são objetos que interagem com os Reducers contidos dentro de uma Store. Eles contêm duas propriedades, Type para descrever o que esta ação faz e Payload para identificar a informação a ser manipulada globalmente.
Figura 2: Ciclo de estado Redux

Apesar da sua utilidade, o Redux pode não ser o mais friendly para Begginers, isto por conter código complexo para quem está a começar em React.js. Redux ajuda a simplificar a lógica de partilhar informação em grandes projetos com muitos componentes, ao ter os estados num único sítio e acessível a todos os componentes da aplicação, indiferente da profundidade em que se encontre o componente. Mas esta simplicidade de lógica, diferente do Props onde passamos dados de componente para componente, pode mesmo assim não justificar o uso de Redux, se o projeto for de menor dimensão com poucos componentes.

Context API

Para o Redux é importante definir uma Store, sítio único que permite prover a informação a ser consumida pela aplicação. Ora estes são os dois conceitos principais por trás do React Context API igualmente, introduzido na atualização do React na versão 16.3. O objetivo é prover globalmente a informação a ser consumida pelo projeto, evitando o constrangimento de ter de passar um valor de componente para componente via Props. Este utiliza principalmente dois tipos de atributos:

  • Provider: Permite identificar qual o componente Pai, este irá fazer a vez de store para guardar os estados do projeto com o createContext(), que irão estar acessíveis a todos os componentes filhos, que para os utilizar devem se identificar como Consumer. Muito diferente dos props onde teremos sempre de passar os estados de componente para componente.
  • Consumer: este permite identificar com ajuda do UseContext() o componente onde será utilizado o valor global que foi definido anteriormente no Provider. Sempre que existir uma alteração do valor original no Provider terá impacto no componente que usufrui desse valor através do Consumer.

A seguir um exemplo de como um valor pode ser partilhado entre componentes, a vários níveis de profundidade, com ajuda do Context API.

import { useState, createContext, useContext } from "react";
import ReactDOM from "react-dom/client";

const ColorContext = createContext();
//Identifica elemento a servir de Provider

function Component1() {
const [color, setColor] = useState("Verde");

return (
<ColorContext.Provider value={color}>
//Todos os componentes dentro desta Tag têm acesso ao estado "color"
<h1>{`Eu gosto da cor ${color}!`}</h1>
<Component2 />
</ColorContext.Provider>
);
}

function Component2() {
return (
<>
<h1>Component 2</h1>
<Component3 />
</>
);
}

function Component3() {
const color= useContext(ColorContext);
//Identifica onde será utilizado o valor do provider

return (
<>
<h1>Component 3</h1>
<h2>{`Gosto mesmo da cor ${color}`}</h2>
//Aplica valor inicialmente guardado no componente Pai
</>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Component1 />);

React Hooks

Os React Hooks são uma adição ao React.js, publicados na versão 16.8 que foi lançada em 2019, muito popularizada pela sua simplicidade de código, tendo como característica principal serem funções para gerir os estados da informação contida num projeto, sem precisar de utilizar classes para esse efeito.

Quando falamos em projetos de menor tamanho, com poucos componentes, os React Hooks serão a escolha mais adequada. Por exemplo ao combinar com outras ferramentas, facilmente é possível partilhar estados entre componentes com ajuda de Props, inclusive aqui utilizar Callback Functions onde podemos altera o estado existente num componente Pai a partir de um componente Filho.

Para fazer a gestão de estado numa aplicação, os Hooks mais importantes e por norma os mais utilizados, são o UseState e o UseEffect. A seguir, falaremos brevemente sobre os dois.

React Hook — UseState

Este hook simplifica a tarefa de atribuir um valor inicial a uma determinada variável de estado, permitindo a sua manipulação com a utilização do SetState, podemos substituir o valor inicial ou utilizar este para criar um valor novo. Anteriormente seria utilizado um Class Component composto por um Constructor com atributos de Super e this.state que iriam acrescentar mais linhas de código e complexidade do que a utilizada com o UseState hook.

No exemplo abaixo, vemos o valor contido numa variável de estado ser alterado devido a uma arrow function que invoca o SetState nessa variável para lhe atribuir um novo valor.

import { useState } from "react";
import ReactDOM from "react-dom/client";

function FavoriteTeam() {
const [team, setTeam] = useState("Benfica");//Definição do estado inicial

return (
<>
<h1>A minha equipe favorita é o {team}!</h1>
<button
type="button"
onClick={() => setTeam("Sporting")}// "Set" para alterar estado
>Sporting</button>
<button
type="button"
onClick={() => setTeam("Sporting")}// isto não é um engano =)
>Porto</button>
</>
)
}

React Hook — UseEffect

Este hook é uma função que interage com os componentes e permite realizar uma determinada ação, tarefa, em função da manipulação de uma variável de estado, o que irá provocar um novo render do componente. Este tem dois parâmetros principais, a passagem de uma função que irá realizar algo e uma dependência, normalmente na forma de um array. Sempre que for invocado o elemento ou objeto associado como dependência será chamado este hook UseEffect e provocado um novo render.

Estes são muito úteis na gestão de estados num pequeno conjunto de componentes, mas que podem gerar confusão quando o projeto cresce e o número de componentes pelos quais tiveres de passar dados via props seja insustentável. Aqui uma solução global é a escolha mais adequada.

No exemplo abaixo temos um contador infinito dentro do componente Timer que altera o valor de Count com ajuda do UseEffect.

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

function Timer() {
const [count, setCount] = useState(0);//Variável de estado

useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
}, [count]); //Dependência é a própria variável "Count"
//Se a dependencia, "array", estiver vazio provoca um único render
//Se não tiver dependencia, "array", irá criar um loop infinito

return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

Como conclusão, podemos identificar os React Hooks e Context API como uma melhoria na evolução natural do React, derivado claramente de ser muito utilizada no desenvolvimento de aplicações web. Não entanto, estes dois não vem com o propósito de suplantar ou fazer esquecer o React Redux, vem sim complementar, simplificar o desenvolvimento na criação de conteúdo web.

Estes tipos de ferramentas não podem ser vistos na ótica de utilizar uma em detrimento da outra, podem sim ser utilizadas em conjunto. Previamente é importante identificar o contexto e dimensão do projeto que formos desenvolver para melhor escolher a metodologia de trabalho. Assim será possível implementar práticas que promovam um código eficiente e reutilizável no nosso projeto.

Espero que esta breve introdução sirva para aguçar a tua curiosidade sobre a gestão de estados dentro de um projeto de React.js. Para mais detalhe podes visitar os links abaixo descritos.

Redux

React Hooks

Context API

--

--

Edgar Quintero
MCTW_TDW

I´m a confident and driven person, open to new horizons. I see in constant learning a path to personal and professional growth.