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.
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.
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;
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>
);
}
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>
);
}
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.
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>
);
}
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.
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;
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
Repare na Animação 1 que a cada clique no botão contador, o valor total será incrementado.
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
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo