Como puxar dados para um componente SEM utilizar props ou redux (React)
Tags: react, javascript
Published: 2021-08-01 15:52:55

---
title: Como puxar dados para um componente SEM utilizar props ou redux (React)
published: true
description: Exemplo de como usar o Context API do React
tags: react, javascript
//cover_image: https://direct_url_to_image.jpg
---

A Context API do React é a sua melhor amiga quando você precisa compartilhar informações entre vários componentes, como o exemplo clássico de um carrinho de compras. 

Imagine que você queira saber em qualquer lugar da sua aplicação se o carrinho está aberto ou fechado. Com a Context API, você pode fazer isso de forma simples e direta, sem precisar ficar passando informações manualmente entre componentes. 

**TL;DR**

1. Primeiro, crie um contexto, que é basicamente uma "área" onde você pode compartilhar informações:

```jsx
const MyContext = React.createContext();
```

2. Em seguida, crie um "Provider" (Fornecedor) que vai conter todos os dados que você quer compartilhar:

```jsx
class MyProvider extends React.Component {
  render() {
    return (
      <MyContext.Provider value={/* Seus dados aqui */}>
        {this.props.children}
      </MyContext.Provider>
    );
  }
}
```

3. Coloque tudo o que você tem na sua aplicação dentro desse "Provider":

```jsx
class App extends React.Component {
  render() {
    return (
      <MyProvider>
        <Component1 />
        <Component2 />
        {/* Qualquer conteúdo aqui */}
      </MyProvider>
    );
  }
}
```

4. Agora, você pode puxar esses dados em qualquer componente que esteja dentro do "Provider" usando o "Consumer" (Consumidor):

```jsx
class Component1 extends React.Component {
  render() {
    return (
      <div>
        <MyContext.Consumer>
          {valor => (
            // Faça o que quiser com os dados aqui
          )}
        </MyContext.Consumer>
      </div>
    );
  }
}
```

O legal é que o "Component1" pode estar dentro do "Component2", que por sua vez está dentro do "Component3". Não importa onde você queira puxar os dados, basta adicionar o "Consumer" e usar a função com os valores que você precisa.

**Passo a passo:**

Suponha que você tenha uma variável chamada "dados" em sua aplicação:

```jsx
class App extends React.Component {
  dados = {
    var1: 'olar',
    var2: 42,
    var3: true
  }

  render() {
    return (
      <div></div>
    );
  }
}
```

Agora, você quer puxar esses dados em outro componente:

```jsx
class Component1 extends React.Component {
  render() {
    return (
      <div>
        {this.props.propriedade}
      </div>
    );
  }
}

class App extends React.Component {
  dados = {
    var1: 'olar',
    var2: 42,
    var3: true
  }

  render() {
    return (
      <div>
        <Component1 propriedade={this.dados.var1} />
      </div>
    );
  }
}
```

Você faria isso usando "props", certo? Mas imagine que você queira criar um "Component2" que puxa dados do "Component1" e rodá-lo em seu aplicativo. Isso pode levar a muita repetição de "props", especialmente se sua cadeia de componentes for longa.

É aí que entra a Context API. Vamos dar uma olhada:

**Context API:**

Primeiro, você cria um contexto usando `React.createContext()`:

```jsx
const MyContext = React.createContext();
```

Em seguida, crie um "Provider" que conterá seus dados:

```jsx
class MyProvider extends React.Component {
  dados = {
    var1: 'olar',
    var2: 42,
    var3: true
  }

  render() {
    return (
      <MyContext.Provider value={this.dados}>
        {this.props.children}
      </MyContext.Provider>
    );
  }
}
```

O "Provider" ficará no nível mais alto da aplicação e você pode passar os dados usando `value`.

Agora, qualquer coisa dentro do "Provider" pode acessar os dados. Mas como puxar esses dados para um componente dentro do "Provider"?

Você não precisa mais usar "props". Em vez disso, você coloca uma propriedade "render" e dentro dela, uma função:

```jsx
<MyContext.Consumer render={/* Sua função aqui */} />
```

Ou, você pode passar o "render" como um "child", e aqui vai um aviso importante: o "child" de um "Consumer" **sempre** será uma função:

```jsx
class Component1 extends React.Component {
  render() {
    return (
      <div>
        <MyContext.Consumer>
          {valor => (
            <p>Estou dentro do consumidor.</p>
          )}
        </MyContext.Consumer>
      </div>
    );
  }
}
```

O que é esse "valor"? Bem, se você usar `{valor}`, ele pegará o valor que está dentro do "Context.Provider", que no nosso exemplo é "this.dados". A partir daí, você pode acessar esses dados em qualquer componente dentro do "Provider".

Aqui está o exemplo final:

```jsx
const MyContext = React.createContext();

class MyProvider extends React.Component {
  dados = {
    var1: 'olar',
    var2: 42,
    var3: true
  }

  render() {
    return (
      <MyContext.Provider value={this.dados}>
        {this.props.children}
      </MyContext.Provider>
    );
  }
}

class Component1 extends React.Component {
  render() {
    return (
      <div>
        <MyContext.Consumer>
          {valor => (
            <p>{valor.var1}</p>
          )}
        </MyContext.Consumer>
      </div>
    );
  }
}

class App extends React.Component {
  render() {
    return (
      <MyProvider>
        <div>
          <Component1 />
        </div>
      </MyProvider>
    );
  }
}
```

Uma observação final: Você pode puxar apenas uma variável dentro dessa função. Se quiser puxar mais de uma, use `React.Fragment` para envolvê-las. Dessa forma, você pode acessar todos os dados de que precisa.
React.Fragment para puxar mais de uma variável no Consumer da Context API:

```jsx
import React from 'react';

const MyContext = React.createContext();

class MyProvider extends React.Component {
  dados = {
    var1: 'olar',
    var2: 42,
    var3: true
  };

  render() {
    return (
      <MyContext.Provider value={this.dados}>
        {this.props.children}
      </MyContext.Provider>
    );
  }
}

class Component1 extends React.Component {
  render() {
    return (
      <div>
        <MyContext.Consumer>
          {valor => (
            <React.Fragment>
              <p>{valor.var1}</p>
              <p>{valor.var2}</p>
            </React.Fragment>
          )}
        </MyContext.Consumer>
      </div>
    );
  }
}

class App extends React.Component {
  render() {
    return (
      <MyProvider>
        <div>
          <Component1 />
        </div>
      </MyProvider>
    );
  }
}

export default App;
```

Neste exemplo, o Component1 está usando React.Fragment para envolver as tags "p". Isso permite que você acesse e exiba múltiplas variáveis do objeto valor que está dentro do Consumer. 

Dessa forma, você pode puxar e renderizar várias variáveis sem a necessidade de criar várias funções Consumer separadas.

Espero que isso tenha esclarecido como a Context API do React pode simplificar bastante o compartilhar de dados entre componentes 👍🚀