React State

React Context API

A Context API é a forma nativa do React de compartilhar estado através de uma árvore de componentes sem a necessidade de passar props por todos os níveis. Quando bem utilizada, ela elimina o prop drilling; quando usada descuidadamente, ela provoca a renderização de tudo.

intermediate13 min readUpdated 15 de set. de 2026
ThemeContext.jsx
jsx
// ThemeContext.jsx
import { createContext, useContext } from "react";

const ThemeContext = createContext("light");

export function useTheme() {
  return useContext(ThemeContext);
}

export function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}
Vem com
React
Pacotes extras
Nenhum
Criado com
createContext
Fornecido por
Context.Provider
Lido com
useContext
Ideal para
Valores compartilhados de baixa frequência

Por que importa

Por que o Context existe

Sem prop drilling

Qualquer componente na árvore pode ler um valor compartilhado diretamente, não importa quão profundamente esteja aninhado.

Zero dependências

O Context faz parte do React, portanto não há nada para instalar e nenhum runtime extra para se preocupar.

Providers compostíveis

Você pode aninhar vários providers e dividir um valor grande em contextos focados para melhor performance.

O panorama completo

As três partes do Context

Um objeto de contexto, um provider que fornece um valor e um hook que o lê. Não há mais nada para aprender.

O objeto de contexto

Identidade

Criado uma única vez com createContext, ele é a chave que os componentes usam para encontrar um provider.

O provider

Fornecimento

Um componente que insere um valor na árvore e renderiza novamente os consumidores quando este muda.

O consumidor

Leitura

O useContext lê o valor do provider mais próximo, e um hook customizado encapsula isso para maior conveniência.

Context em resumo

O núcleo do Context

createContext

Define um contexto com um valor padrão usado quando nenhum provider está presente.

Provider

Envolve uma subárvore e passa o valor atual para cada consumidor abaixo.

useContext

Lê o valor do provider mais próximo dentro de qualquer componente.

Hooks customizados

Encapsule o useContext em um hook para que quem o chame tenha uma API clara e verificações de erro.

Divisão de contextos

Separe estado e ações para que os consumidores renderizem novamente apenas o que utilizam.

Performance

O Context renderiza novamente todos os consumidores na mudança, portanto mantenha os valores estáveis e focados.

Uma breve historia

De API oculta a recurso de primeira classe

  1. 2018

    Context torna-se estável

    O React 16.3 lança a Context API suportada após anos de uma versão experimental.

    18
  2. 2019

    Chegada dos Hooks

    O useContext torna o consumo de contexto uma linha única de código e substitui as render props.

    19
  3. 2021

    Context e performance

    A comunidade adota a divisão de contextos e a memorização de valores como a melhor prática.

    21
  4. Hoje

    Uma ferramenta nativa

    O Context é o padrão para temas, autenticação e locale, enquanto stores lidam com estados de alta frequência.

    Hoje

O guia completo

React Context API: Tudo que voce precisa saber

O que é a Context API?

A Context API é a forma nativa do React de passar dados através de uma árvore de componentes sem a necessidade de passar props por todos os níveis. Ela resolve um problema específico e comum: quando um valor é necessário para muitos componentes, mas está localizado muito acima deles na árvore.

O exemplo clássico é a tematização (theming). Um Button localizado no fundo da árvore precisa do tema atual, mas cada componente entre o topo e o botão teria que aceitar e encaminhar uma prop theme. Isso é chamado de prop drilling, e o Context elimina esse problema. Você fornece o valor apenas uma vez, e qualquer descendente pode lê-lo diretamente.

Criando e fornecendo contexto

O contexto é composto por três partes: um objeto, um provider e um hook de consumo.

// AuthContext.jsx
import { createContext, useContext, useMemo, useState } from "react";

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const value = useMemo(
    () => ({
      user,
      login: (nextUser) => setUser(nextUser),
      logout: () => setUser(null),
    }),
    [user],
  );

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

createContext define o contexto e um valor padrão. O provider fornece o valor atual para tudo o que estiver abaixo dele. O hook customizado lê esse valor e retorna um erro claro caso o componente seja utilizado fora do provider.

Consumindo o contexto

Qualquer descendente pode ler o valor, não importa quão profundo esteja na árvore.

// Header.jsx
import { useAuth } from "./AuthContext";

export function Header() {
  const { user, logout } = useAuth();

  return (
    <header>
      <span>{user ? `Hi, ${user.name}` : "Guest"}</span>
      {user && <button onClick={logout}>Sign out</button>}
    </header>
  );
}

O Header nunca recebeu uma prop do App. Ele buscou na árvore o valor de que precisava, o que mantém os componentes intermediários alheios aos dados que não utilizam.

Context não é estado

Essa distinção costuma confundir as pessoas. O Context não armazena estado nem gerencia atualizações. Ele transporta um valor. O estado em si reside em useState ou useReducer, e o provider o repassa para baixo.

É por isso que um padrão comum é combinar context com um reducer:

// CartContext.jsx
import { createContext, useContext, useReducer } from "react";

const CartContext = createContext(null);

function reducer(state, action) {
  switch (action.type) {
    case "add":
      return [...state, action.item];
    case "remove":
      return state.filter((item) => item.id !== action.id);
    default:
      return state;
  }
}

export function CartProvider({ children }) {
  const [items, dispatch] = useReducer(reducer, []);
  return (
    <CartContext.Provider value={{ items, dispatch }}>
      {children}
    </CartContext.Provider>
  );
}

export const useCart = () => useContext(CartContext);

O reducer mantém as atualizações previsíveis, e o context as torna disponíveis em qualquer lugar sem a necessidade de prop drilling.

Performance: a real limitação

Quando o valor de um provider muda, todos os componentes que leem esse contexto são renderizados novamente. Não existe um selector, portanto você não pode se inscrever em apenas uma parte do valor. Dois hábitos tornam isso gerenciável.

Memorize o valor. Um objeto literal cria uma nova referência a cada renderização, o que significa que cada consumidor será renderizado novamente mesmo quando nada mudou.

// memoised
const value = useMemo(() => ({ user, logout }), [user]);

Divida os contextos. Coloque estados e ações em contextos separados, ou divida por funcionalidade, para que um componente que precisa apenas disparar uma ação não seja renderizado novamente quando o estado mudar.

// split.jsx
const CartStateContext = createContext(null);
const CartActionsContext = createContext(null);

Componentes que apenas chamam ações se inscrevem no contexto de ações, que nunca muda de identidade, portanto, eles nunca sofrem re-render devido a uma atualização de estado. Esse único truque resolve a maioria das reclamações de performance relacionadas a contextos.

Quando usar Context, e quando não usar

O Context é a ferramenta certa para:

  • Temas e modo de cores.
  • Usuário autenticado e sessão.
  • Locale e traduções.
  • Um router ou uma configuração pequena e estável.

Opte por um store dedicado quando você tiver:

  • Atualizações frequentes, como digitação, arraste (dragging) ou animações.
  • Uma árvore de estado grande onde os componentes precisam de selectors.
  • Necessidade de middleware, persistência ou devtools de time-travel.
  • Estado de servidor que precise de caching e refetching.

Bibliotecas como Zustand e Redux Toolkit adicionam selectors para que os componentes assinem fatias (slices) em vez do valor completo. Para dados de servidor, o TanStack Query gerencia o caching integralmente.

Melhores práticas

  • Envolva useContext em um custom hook e verifique se o provider está ausente.
  • Memorize os valores do provider com useMemo.
  • Divida os contextos por responsabilidade, especialmente estado versus ações.
  • Mantenha os valores do contexto pequenos e focados.
  • Use useReducer quando as atualizações forem complexas ou dependerem do estado anterior.
  • Não utilize contexto para atualizações de alta frequência; utilize um store baseado em seletores.
  • Forneça valores padrão sensatos para que os componentes possam renderizar fora de um provider quando apropriado.

Erros comuns

  • Tratar o context como um gerenciador de estado e esperar por selectors.
  • Passar um objeto inline como valor do provider e causar a renderização de tudo novamente.
  • Colocar dados não relacionados em um único context gigante.
  • Esquecer o valor padrão e causar um crash em undefined.
  • Usar context para valores que apenas um ou dois componentes precisam.
  • Esperar que o context otimize as re-renders automaticamente.

Próximos passos

O Context é a base do compartilhamento de estado no React, e conhecer seus limites indica quando é hora de evoluir. Compare-o com o Redux Toolkit para estados previsíveis em larga escala e com o Zustand para um store de seletores leve; depois, gerencie dados do servidor com o TanStack Query. Para Vue, o conceito equivalente é abordado no guia do Pinia.

Compartilhando um valor

Context serve para valores que muitos componentes precisam, como tema ou o usuário atual. Não é um substituto para todas as props.

Preferir
const ThemeContext = createContext("light");

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme} />;
}
Evitar
function Button({ theme }) {
  return <button className={theme} />;
}
// drilled through every
// level of the tree

Fornecendo um valor

Um objeto inline cria uma nova referência a cada renderização, forçando a renderização de todos os consumidores. Memorize-o.

Preferir
const value = useMemo(
  () => ({ user, logout }),
  [user],
);

<AuthContext.Provider value={value}>
  {children}
</AuthContext.Provider>
Evitar
<AuthContext.Provider
  value={{ user, logout }}
>
  {children}
</AuthContext.Provider>

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender Context API?

Nosso tutorial interativo te guia por Context API passo a passo — com quizzes e codigo real que voce pode executar no navegador.