React.JS: Passando dados com Context API

Neste artigo abordaremos um assunto bastante interessante no React chamado context, que disponibiliza uma maneira de passar os dados entre a árvore de componentes sem precisar passar props manualmente em cada nível.

O que é o Context API?

No React, quando precisamos que um componente filho tenha os dados do pai, precisamos informar esses dados e funções através das props no componente filho, como pode ser visto na Figura 1.

Figura 1. Componente filho recebendo props do componente pai

Com a chegada do Context API no React (a partir da versão 16) esse cenário é diferente, ao invés de passar esses dados através de props, criamos um context que armazena esses dados. Dessa forma, os componentes que precisam dessa informação podem consumi-las. Esse processo possui o mesmo princípio do Redux, sendo que o Context API é nativo no próprio React. Caso você já possua conhecimento prévio em Redux, será mais fácil entender e como usar o Context API, por conta que eles possuem a mesma filosofia, gerenciamento de estados.

Porque o Context é útil?

O conceito de estado ficou complexo à medida que foi necessário compartilhar o estado dentro da aplicação de uma forma global entre os componentes. Para isso, algumas bibliotecas surgiram para resolver essa nova demanda, como o Redux e MobEx. O Redux é a biblioteca mais utilizada para gerenciamento de estados.

O React context API é um gerenciador de estado global e é uma funcionalidade implementada a pouco tempo no ecossistema do React, podendo resolver 90% das soluções do Redux de forma extremamente simples.

Na Figura 2 temos uma representação mais ilustrativa da diferença do uso de props e de Context API.

Figura 2. Diferença do uso de props e context API

Note que sem a utilização do context, os dados serão repassados através da árvore de componentes (componente através do outro). Já usando o context, esses mesmos dados já estarão disponíveis e compartilhados por todos os componentes que precisarem dessa informação.

Aplicando context

Neste ponto criaremos um exemplo de contador que incrementará um valor ao ser clicado utilizando o Context API.

Primeiramente vamos criar um arquivo que gerenciará o nosso contexto, chamado Context.js. Veja o seu código no Código 1.

import React, { createContext } from 'react'; const Context = createContext(0); export default Context;
Código 1. Código do arquivo Context.js

Explicando o código.

Linha 1: Importamos o React, e junto com ele colocaremos em chaves a função de createContext.

Linha 3: Vamos criar um contexto chamado Context. Para isso utilizamos a função createContext que recebe 0 como valor inicial. Feito isso, o contexto foi criado.

Linha 5: Exportamos o nosso Context para ser utilizado por todos os componentes que importá-lo.

Agora importaremos nosso contexto criado no arquivo App.js (Código 2) para que dentro dele seja inserido os componentes que poderão compartilhar os dados salvos no contexto.

import React from 'react'; import Context from './Context'; export default function App() { return ( <Context.Provider> <div> <p> DevMedia Context API</p> </div> </Context.Provider> ); }
Código 2. Arquivo App.js importando o contexto Context

Explicando o código:

Linha 1: Importamos o React.

Linha 2: Importamos o contexto criado em context.js, pra usá-lo no nosso arquivo App.js

Linha 4: Criamos um componente funcional declarado como App, com o mesmo nome do nosso arquivo, e o exportamos na mesma linha.

Linha 6: Usaremos a constante Context da mesma forma que um componente, ou seja, com tag de abertura e fechamento. Repare que aqui utilizamos Context.Provider para que dentro dele possamos inserir os componentes que podem utilizar este contexto. Com isso, todos os componentes dentro de Context.Provider poderão utilizar o contexto Context.

Agora criaremos o componente de Counter, que vai exibir o botão que altera o valor da variável total que será armazenada no contexto, conforme o Código 3.

import React, { useContext } from "react"; import Context from "./Context"; export default function Counter() { const [total, setTotal] = useContext(Context); return ( <div> <h3></h3> <button type="button" onClick={() => setTotal(total + 1)}> Contador </button> </div> ); }
Código 3. Criando o componente Counter

Explicando o código:

Linha 1: Usaremos o hook useContext para conseguirmos usar o contexto.

Linha 3: Com o useContext proporcionaremos o nosso contexto dentro do nosso componente que queremos utilizar. Essa função retorna ao componente o valor do contexto atual. Lembrando que para acessar esse valor o componente precisa estar inserido no provider do contexto (componente Context.Provider inserido no componente do arquivo App.js).

Linha 5: Declaramos e exportamos o componente funcional de Counter.

Linha 6: Usando o useContext receberemos os dados do contexto Context. O valor total atual do contador e o setTotal é a função que será usada para atualizar total a cada clique do usuário. Esse código é similar a criação de uma variável de estado utilizando useState, isso porque nosso contexto vai armazenar uma variável de estado.

Linha 10: Imprime o valor atual (valor armazenado no contexto) usando a expressão do JSX, entre as chaves.

Linha 11: Criamos um botão do tipo button, e na sua propriedade onClick uma função anônima que a cada clique receberá o valor atual do total incrementado de 1.

Neste momento temos a estrutura básica para entender o conceito de Context API. Neste momento ainda não funcionará do jeito que queremos, ou seja, exibindo o valor do contador e o botão para incrementar um a cada clique. Veja a aparência atual do projeto na Figura 3.

Figura 3. Aparência atual do projeto

Para que a aplicação exiba o botão que vai utilizar o contexto, precisamos fazer algumas alterações no nosso projeto.

Primeiramente modificaremos o arquivo App.js para implementar o hook useState. É através dele que vamos criar a variável que armazenará o valor que será exibido e incrementado pelo botão.

Veja no Código 4 o componente App atualizado.

import React, { useState } from 'react'; import Context from './Context'; import Counter from './Counter'; export default function App() { const [total, setTotal] = useState(0); return ( <Context.Provider value={[total, setTotal]}> <div> <p>App.js: { total }</p> <p> DevMedia Context API</p> <Counter /> </div> </Context.Provider> ); }
Código 4. Componente App criando a variável de estado

Entenda o que alteramos:

Linha 1: Neste ponto além do React importamos também, o useState.

Linha 3: Importamos o componente de Counter.js que exibe o botão que incrementará a variável total.

Linha 6: Usamos o useState para criar uma variável de estado que terá um valor inicial de 0. Lembrando que total é a variável de estado e setTotal é a função que vai alterar o seu valor.

Linha 9: No Context.Provider passamos um parâmetro chamado value que armazenará a variável de estado que criamos utilizando o useState. A ordem inserida (variável e função) é importante para termos a consistência dos dados que serão transmitidos dentro do contexto. A partir deste momento, já é possível usar o contexto sempre que houver necessidade. Lembrando que os componentes devem estar dentro do meu Provider.

Linha 11: Imprimimos o valor total em nosso componente App.js.

Linha 13: Invocaremos o nosso componente Counter.js.

O componente Couter só consegue utilizar o contexto Context porque ele está inserido dentro de Context.Provider.

Para deixarmos nosso contexto padronizado com o valor que ele receberá, vamos atualizar o arquivo Context.js como exibido no Código 5.

import React, { createContext } from 'react'; const Context = createContext([0, () => {}]); export default Context;
Código 5. Arquivo Context padronizado com o valor que ele vai receber em App.js

Repare que a alteração feita está padronizada com o código usado para criar a variável de estado através de useState, ou seja, uma variável e uma função.

Agora podemos acessar o terminal onde está o projeto e executá-lo usando o Código 6.

npm start
Código 6. Comando usado para executar a aplicação

Repare na Animação 1 que a cada clique no botão contador, o valor total será incrementado.

Animação 1. Projeto criado utilizando o contexto

Veja no flow abaixo o resumo do projeto criado:

Conclusão

O Context é uma ferramenta poderosa dentro do React. Ela é usada para gerenciar os estados dos seus componentes dentro de uma aplicação web sem precisar usar algum pacote para isso. Espero que tenham gostado e até a próxima.

Artigos relacionados