DEV Community

Mica Mica
Mica Mica

Posted on • Edited on

Como puxar dados para um componente SEM utilizar props ou redux (React)

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:
const MyContext = React.createContext();
Enter fullscreen mode Exit fullscreen mode
  1. Em seguida, crie um "Provider" (Fornecedor) que vai conter todos os dados que você quer compartilhar:
class MyProvider extends React.Component {
  render() {
    return (
      <MyContext.Provider value={/* Seus dados aqui */}>
        {this.props.children}
      </MyContext.Provider>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Coloque tudo o que você tem na sua aplicação dentro desse "Provider":
class App extends React.Component {
  render() {
    return (
      <MyProvider>
        <Component1 />
        <Component2 />
        {/* Qualquer conteúdo aqui */}
      </MyProvider>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Agora, você pode puxar esses dados em qualquer componente que esteja dentro do "Provider" usando o "Consumer" (Consumidor):
class Component1 extends React.Component {
  render() {
    return (
      <div>
        <MyContext.Consumer>
          {valor => (
            // Faça o que quiser com os dados aqui
          )}
        </MyContext.Consumer>
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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:

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

  render() {
    return (
      <div></div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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

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>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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():

const MyContext = React.createContext();
Enter fullscreen mode Exit fullscreen mode

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

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

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

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:

<MyContext.Consumer render={/* Sua função aqui */} />
Enter fullscreen mode Exit fullscreen mode

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:

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

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:

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>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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:

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;
Enter fullscreen mode Exit fullscreen mode

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 👍🚀

Top comments (0)