Conhecendo a React Context API
Tags: react, redux, javascript, typescript
Published: 2020-07-06 23:39:20

Os novos front-ends contruidos com os frameworks mais atuais geraram por consequencia, maiores complexidades no que antes seria apenas construido com HTML+CSS+JS. Muitos termos e conhecimentos surgiram em conjunto com esses frameworks, e um deles é o *estado da aplicação*. Basicamente, cada componente que construímos possui em sí próprio uma base de dados em que ele se alimenta e escuta conforme suas modificações vão acontecendo.

O conceito de estado tomou sua devida complexidade quando foi necessário compartilhar o estado da aplicação de forma global entre os componentes de sua aplicação. Para isso, varias bibliotecas surgiram, como o Redux, MobEx e etc. O Redux, em teoria, seria a biblioteca mais utilizada para este fim entre os programadores React, e muitos deles acham sua usabilidade terrível. 

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

Então, que tal aprendermos como utiliza-lo hoje? Vamos lá?

###**O que é um contexto?**

O contexto, segundo o dicionário é definido como uma inter-relação de circunstâncias que acompanham um fato ou uma situação. A nossa situação no caso, seriam nosso componentes. Imagine que estamos em um carrinho de compras e esse carrinho precisa guardar o estado dos produtos anto na tela de carrinho quanto estiver com o carrinho aberto, quanto na página de listagem de produtos? Como resolveríamos isso?

#### Da forma antiga

Poderíamos criar vários componentes e passar os dados via props para cada componente. Assim, quando o componente de carrinho for  renderizado, para cada clique de produto que o cliente deseje **adicionar ao carrinho**, deve-se chamar novamente o componente do carrinho, alterando suas props, e dentro do próprio carrinho, gerenciar todos esses dados que serão escutados por varios produtos diferentes na própria página...
Ufa! Só isso? Achou complexo?

#### Com o Context API

Utilizamos um contexto que engloba todos os componentes do app, e sempre que um produto for adicionado ao carrinho, o contexto será atualizado e notificará todos os componentes. Assim, nosso carrinho precisa apenas puxar as informações do contexto global da aplicação. 
Simples né?

#### Uma imagem vale mais que mil palavras

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nfdmezedooow2m0clyh3.png)

Perceba que, sem a context, precisamos passar de forma encadeada, cada um dos dados, e sem ela, o contexto engloba todos os componentes de uma vez.

###**Vamos ao código?**

Vamos construir um aplicativo de e-commerce através do *create-react-app*. Para isso, precisamos de um componente de carrinho e um componente de lista com os produtos. Precisamos que o *estado se compartilhe entre os dois* para que um saiba o que o outro sabe. 

####**Criando o contexto**

A primeira coisa que precisamos fazer é definir nosso contexto. Para isso, criamos ao lado do nosso arquivo de **App.js** um arquivo chamado **AppContext.js**. E importaremos, além de nossas depentencias comuns como useEffect e useState, a useContext e é ela que fará toda a mágica.

Para definir um contexto, usamos o useContext como mostrado abaixo:

```javascript
import React, { useState, useEffect, createContext } from 'react';

export const AppContext = createContext();

```

####**Criando o estado**

Com isso, criamos um contexto que englobará todo o App. Com o contexto criado, criaremos nele o estado do nosso carrinho através do useState:

```javascript
export const Provider = (props) => {
  const [cart, setCart] = useState([]);
}
```

####**Retornando o contexto**

Por fim, com o estado criado, teremos agora que disponibilizar o estado para os componentes dentro do App. Fazemos isso com uma função de retorno da forma a seguir:

```javascript
  return (
    <AppContext.Provider value={[drivers, setDrivers]}>
      {props.children}
    </AppContext.Provider>
  )
```

Nosso arquivo **AppContext.js** ficará assim:

```javascript
import React, { useState, useEffect, createContext } from 'react';

export const AppContext = createContext();


export const Provider = (props) => {
  const [cart, setCart] = useState([]);

  return (
    <AppContext.Provider value={[drivers, setDrivers]}>
      {props.children}
    </AppContext.Provider>
  )
}

```

###**E agora, o que precisamos?**

Com nosso contexto criado, basta importa-lo no **App.js** e pronto, você já pode utiliza-lo. Veja abaixo como:

```javascript
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import Routes from './routes';
import { Provider } from './AppContext'

function App() {
  return (
    <Provider>
      <BrowserRouter>
        <Routes />
      </BrowserRouter>
    </Provider>
  );
}

export default App;
```

Assumindo que nosso componentes se encontram no Router Dom, automaticamente com o Provider, podemos fazer com que eles escutem o estado global.

###**E como eu chamo o estado no meu componente?**

Vamos imaginar que estamos no componente **Cart.js**. O que faremos para chamar o contexto do estado? Apenas, inserir o código abaixo:

```javascript
import React, { useContext } from 'react'
import { AppContext } from '../../AppContext'

export default function Cart() {
  const [cart, setCart] = useContext(AppContext)
}
```

Pronto! Nosso Cart já pode utilizar as funções que utilizaria normalmente em seu estado interno. Cada vez que você chamar *setCart()* todo o App escutará essas mudanças, sem necessidade de Reducers, nem Actions, nem Dispatch, nem nada disso. Simples não?
 
**Lembre-se que você pode ter inúmeros contextos dentro de uma mesma aplicação.**

Obrigado por mais uma leitura!