DEV Community

loading...

Como usar o Context API do React

Michelle Azevedo
front end developer and yogini 🧘‍♀️
・4 min read

Como puxar dados de um componente para o outro, sem usar props?

TL;DR

  1. Criar uma constante que chame a função createContext do react:
const Contexto = React.createContext();
Enter fullscreen mode Exit fullscreen mode
  1. Criar um componente/classe com todos os dados e/ou funções que você quer passar para o resto da aplicação:
const Contexto = React.createContext();

// Componente Provedor
class Provedor extends React.Component {

    render() {
        return(
            <Contexto.Provedor value={}>
                {this.props.children}
            </Contexto.Provedor>
)
    }
Enter fullscreen mode Exit fullscreen mode
  1. Colocar tudo o que você tem no seu app dentro desse Provedor.
class App extends React.Component {
render() {
    return(
<Provedor>
    <Componente1 />
    <Componente2 />
    Qualquer conteúdo aqui.
</Provedor>
    )
}
Enter fullscreen mode Exit fullscreen mode
  1. Puxar os dados em qualquer componente que estiver dentro do provedor:
class Componente1 extends React.Component {
    render() {
    return (
        <div>
            <Contexto.Consumidor>
                {(valor) => (
            escrever o componente e puxar qualquer dado aqui.
) }
            </Contexto.Consumidor>
        </div>
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

O componente1 pode estar dentro do componente2, que esta dentro do componente3, não importa, de onde quer que você queira puxar o dado, basta adicionar o e puxar uma child/renderizar uma função com os valores que precisa utilizar.

🚨 Para decorar: O child de uma função é SEMPRE uma função.

Um ótimo exemplo de utilização é para gravar dados da UI, por exemplo, se o usuário guardou coisas no carrinho, se qualquer outro nível mais baixo da aplicação quiser saber se o carrinho de compras esta aberto, eu puxo um consumidor nesse componente e pergunto lá para cima, se o carrinho esta aberto... e posso até mudar o estado, se necessário.


Passo a passo

o app tem uma variável (dados) com alguns objetos dentro dela:

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

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

quero puxar esses dados, mas eu estou em outro componente:

class Componente1 extends React.Component {
    render() {
    return (
        <div>

        </div>
        )
    }
}

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

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

faço isso via props, certo?

class Componente1 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><Outro propriedade={this.dados.var1} /></div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Dentro do app que você quer puxar o dado: crio uma propriedade com um nome qualquer, nesse caso escolhi "propriedade" mesmo e chamo a variável dados e algo ainda dentro dela.

Dentro do app que vai pegar o dado: apenas puxar o nome da propriedade {this.props.propriedade}.

mas vamos supor que queremos fazer um componente2, que puxa dados do componente1 e vamos rodar no app o componente2. Haveria uma repetição para passar dados de um componente para ou outro via props, numa cadeia de props que, dependendo do tamanho, fica mais fácil usar o Redux e guardar os dados fora da aplicação e puxar dentro de qualquer nível que for necessário, sem ter que ficar passando de um para o outro.

Daí surge o Context API, que usa os conceitos provider e consumer:

const Contexto = React.createContext();

// Componente Provedor
class Provedor extends React.Component {
    dados = {
    var1: 'olar',
    var2: 42,
    var3: true
}
    render() {
        return(
            <Contexto.Provedor value="valor qualquer">
                {this.props.children}
            </Contexto.Provedor>
)
    }
}
Enter fullscreen mode Exit fullscreen mode

O contexto.provedor vai estar no alto nível da aplicação e dentro dele haverá outro componente para acessar o dado. Então vamos passar esse value para qualquer coisa que esteja envolta pelo provedor:


const Contexto = React.createContext();

// Componente Provedor
class Provedor extends React.Component {
    dados = {
    var1: 'olar',
    var2: 42,
    var3: true
}
    render() {
        return(
            <Contexto.Provedor value="valor qualquer">
                {this.props.children}
            </Contexto.Provedor>
)
    }
}

class Componente1 extends React.Component {
    render() {
    return (
        <div>
        {this.props.propriedade}
        </div>
        )
    }
}

class App extends React.Component {
render() {
    return(
<Provedor>
        <div><Outro propriedade={this.dados.var1} /></div>
</Provedor>
    )
}
Enter fullscreen mode Exit fullscreen mode

Então qualquer coisa que estiver dentro do provedor, pode acessar os dados que estão dentro dele... Mas como puxamos os dados do provedor, para algum componente dentro dele?

O dado não é puxado via props, a gente coloca uma propriedade "render" e dentro dela uma função:

<Contexto.Consumidor render=função aqui />
Enter fullscreen mode Exit fullscreen mode

ou passa o render como uma child e, atenção! o child de um consumidor será SEMPRE uma função:

// Consumidor
class Componente1 extends React.Component {
    render() {
    return (
        <div>
            <Contexto.Consumidor render>
                {(valor) => (
                    <p>Eu estou dentro do consumidor.</p>
                    ) }
            </Contexto.Consumidor>
        </div>
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

O que seria o valor? se você puxar o {valor}, ele vai chamar o value que esta dentro do Contexto.Provedor, que é... "valor qualquer". A partir daí, você pode, ao invés de chamar um valor qualquer, chamar a variável dados e, em qualquer componente dentro do Provedor, puxar esses dados.

Exemplo final:


const Contexto = React.createContext();

// Componente Provedor
class Provedor extends React.Component {
    dados = {
    var1: 'olar',
    var2: 42,
    var3: true
}
    render() {
        return(
            <Contexto.Provedor value={{dados: this.dados}}>
                {this.props.children}
            </Contexto.Provedor>
)
    }
}

// Componente que puxa um componente consumidor
class Componente1 extends React.Component {
    render() {
    return (
        <div>
            <Contexto.Consumidor render>
                {(valor) => (
                    <p>{contexto.dados.var1}</p>
                    ) }
            </Contexto.Consumidor>
        </div>
        )
    }
}

class App extends React.Component {
render() {
    return(
<Provedor>
        <div><Componente1 propriedade={this.dados.var1} /></div>
</Provedor>
    )
}
Enter fullscreen mode Exit fullscreen mode

Um adendo: só é possível puxar uma variável dentro dessa função. Para puxar mais de uma, é preciso utilizar o React.Fragment, da seguinte forma:

            <Contexto.Consumidor>
                {(valor) => (
<React.Fragment>
                    <p>{contexto.dados.var1}</p>
                    <p>{contexto.dados.var2}</p>
</React.Fragment>
                    ) }
            </Contexto.Consumidor>
Enter fullscreen mode Exit fullscreen mode

🚨 funções são chamadas de ações no redux.

Discussion (0)