Sep 07, 2022

Nesse artigo lhe ensino como compartilhar um estado globalmente para vários components utilizando a ContextAPI

2 minutos de leitura

Quais são as dores que a contextAPI resolve ?

No React quando temos vários níveis de propriedades sendo passadas de pai para filho, de filho para neto e assim sucessivamente, cometemos uma prática que chamamos de prop drilling ou na sua tradução perfuração de propriedades, que a depender da quantidade de componentes pode acabar complicando muito, deixando mais verboso o seu código, mais difícil a manutenção, e nós como bons programadores queremos poupar dor de cabeça, e pra isso o React tem um state management nativo que vem com intuito de solucionar essa dor, que é a contextAPI.

Uma ilustração de exemplo de como é feito a passagem de propriedades no reactjs o famoso props drilling

Tá, mas como usar essa tal contextAPI ?

É indicado utilizar a context para compartilhar dados que podem ser considerados “globais” na sua aplicação. Usuário autenticado, idioma preferido, temas, são alguns casos comuns.

Mão no código!

  1. Vamos criar 3 components( App, ToggleTheme e Button). O componente App renderizará o componente ToggleTheme que renderizará o componente Button.
import { ToggleTheme } from "./components/ToggleTheme";
 
export function App() {
  return <ToggleTheme />;
}
import { Button } from "./Button";
 
export function ToggleTheme() {
  return <Button />;
}
export function Button() {
  return <button>Mudar tema</button>;
}
  1. Agora importamos de dentro de React o createContext, com ele iremos criar o nosso contexto, e em seguida definiremos o nosso ThemeContext que será o nosso contexto de "tema".

CreateContext recebe como parâmetro um valor padrão, como o nosso contexto é de tema o valor padrão será: "dark".

import { createContext } from "react";
 
// Cada context nos permite passar um valor a fundo da árvore de componente
// sem explicitamente passa-la por cada componente.
const ThemeContext = createContext("dark");

Todos consumidores que são descendentes de um Provider serão renderizados novamente sempre que a prop value do Provider for alterada.

function App() {
  const [theme, setTheme] = useState("dark");
 
  const toggleTheme = () => {
    setTheme(theme === "dark" ? "light" : "dark");
  };
 
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <ToggleTheme />
    </ThemeContext.Provider>
  );
}
  1. Nosso componente ToggleTheme, não precisa mais passar o tema explicitamente. Não precisamos jogar nenhuma propriedade para dentro do componente Button.
function ToggleTheme() {
  return <Button />;
}
  1. Por fim nosso componente Button que receberá os dados da nossa context. Pra isso vamos desestruturar de dentro de useContext o nosso state theme, e a nossa função toggleTheme.

useContext é uma função que recebe como parâmetro o nosso contexto

function Button() {
  const { theme, toggleTheme } = useContext(ThemeContext);
 
  return (
    // Todas as vezes que o botão for clicado o valor de state será alterado
    <button onClick={toggleTheme}>
      {/* Valor do tema sendo mostrado em tela */}
      {theme}
    </button>
  );
}

Aplicação final, sendo ilustrado em um gif

7.Ficando assim o nosso código final

import { createContext, useContext, useState } from "react";
 
const ThemeContext = createContext("dark");
 
function App() {
  const [theme, setTheme] = useState("dark");
 
  const toggleTheme = () => {
    setTheme(theme === "dark" ? "light" : "dark");
  };
 
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <ToggleTheme />
    </ThemeContext.Provider>
  );
}
 
function ToggleTheme() {
  return <Button />;
}
 
function Button() {
  const { theme, toggleTheme } = useContext(ThemeContext);
 
  return <button onClick={toggleTheme}>{theme}</button>;
}
 
export default App;