useContext é um hook React que fornece aos componentes funcionais acesso direto aos dados de um contexto criado através de createContext. O contexto no React resolve o problema de props drilling — passar props através de vários componentes intermediários que não usam esses dados por si só. De acordo com a React Documentation (2025), useContext recebe um objeto de contexto e retorna o valor atual definido pelo Provider mais próximo acima na árvore de componentes. Quando o valor no Provider muda, todos os componentes que usam useContext são renderizados novamente automaticamente.
Pontos principais
useContext é um hook adicionado no React 16.8 juntamente com outros hooks que permite ler um valor do contexto do React. O contexto é um mecanismo incorporado no React projetado para passar dados através da árvore de componentes sem a necessidade de passar props manualmente em cada nível. O useContext substitui o componente Consumer da antiga Context API e torna o código mais conciso e legível.
Os casos de uso típicos do contexto incluem temas (claro/escuro), localidade e traduções (i18n), autenticação de usuário, configurações da aplicação e qualquer outro dado global que muitos componentes em diferentes níveis de aninhamento precisam. A equipe do React recomenda usar o contexto para dados que são globais para uma subárvore de componentes, mas não para toda a aplicação.
De acordo com a React Team — Documentação de contexto (2025), o uso incorreto do contexto é uma das principais causas de problemas de desempenho em aplicações React. Cada alteração de valor no Provider provoca uma re-renderização de todos os consumidores, independentemente de qual parte dos dados mudou. A otimização através de useMemo e da divisão de contextos resolve este problema.
import { createContext, useContext } from 'react';
// Criar contexto com valor padrão
const ThemeContext = createContext('claro');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={`btn-${theme}`}>Click</button>;
}
O mecanismo de contexto no React é implementado através do padrão Provider-Consumer. O createContext retorna um objeto com duas entidades: Provider — um componente que transmite o valor, e o próprio objeto de contexto, que é usado no useContext. O Provider é montado na árvore de componentes e transmite o valor a todos os elementos filhos independentemente da profundidade do aninhamento.
Quando o React encontra uma chamada useContext, ele percorre a árvore fiber procurando o Provider mais próximo para aquele contexto. Se um Provider for encontrado, seu valor é retornado. Se nenhum Provider for encontrado, o valor padrão passado para createContext é retornado. Esta busca ocorre em cada renderização, mas graças à memoização de nós fiber é muito rápida e não afeta o desempenho.
De acordo com React — Internos do contexto (2024), a implementação interna do useContext usa uma lista ligada de hooks, semelhante ao useState. Cada hook armazena uma referência a um nó fiber, permitindo que o React determine rapidamente qual Provider corresponde àquele contexto. Quando um Provider atualiza seu valor, o React marca todos os nós fiber que usam aquele contexto para re-renderização.
Os componentes Provider podem ser aninhados uns dentro dos outros, criando uma hierarquia de contextos. Cada Provider filho sobrescreve o valor do pai para sua própria subárvore. Isso é útil quando um ecrã precisa de um tema claro enquanto uma janela modal aninhada precisa de um tema escuro. O useContext sempre retorna o valor do Provider mais próximo acima na árvore.
const UserContext = createContext(null);
const ThemeContext = createContext('claro');
function App() {
return (
<UserContext.Provider value={{ name: 'Alice' }}>
<ThemeContext.Provider value='dark'>
<Profile />
</ThemeContext.Provider>
</UserContext.Provider>
);
}
A função createContext(defaultValue) cria um objeto de contexto. O parâmetro defaultValue é usado quando um componente chama useContext mas não há um Provider correspondente acima na árvore. Sem defaultValue, useContext retornará undefined, o que pode levar a erros inesperados. Recomenda-se sempre passar um valor padrão significativo ou null.
Criar um provedor personalizado é um padrão comum para encapsular a lógica do contexto. Dentro desse provedor, o estado é armazenado (via useState ou useReducer) e fornecido através da prop value do Provider. Isso esconde os detalhes de implementação dos componentes consumidores e centraliza a lógica de gerenciamento do contexto em um único lugar.
// Provedor personalizado com gerenciamento de estado
const AuthContext = createContext(null);
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = useCallback(async (email, pass) => {
const u = await loginApi(email, pass);
setUser(u);
}, []);
return (
<AuthContext.Provider value={{ user, login }}>
{children}
</AuthContext.Provider>
);
}
Em componentes funcionais, useContext é a única forma de acessar o contexto. Ele substitui o componente Consumer da antiga Context API, que exigia o padrão render-prop: <ThemeContext.Consumer>{value => ...}</ThemeContext.Consumer>. O useContext torna o código mais linear e legível, especialmente ao trabalhar com múltiplos contextos em um mesmo componente.
Ao usar múltiplos contextos em um componente, simplesmente chame useContext várias vezes para cada contexto. Cada chamada retorna o valor do Provider correspondente. A ordem das chamadas não importa, já que cada contexto é uma entidade independente. O React otimiza múltiplas chamadas através do mesmo sistema de referências fiber.
function Dashboard() {
const { user } = useContext(AuthContext);
const theme = useContext(ThemeContext);
const { locale } = useContext(I18nContext);
return (
<div className={`dashboard-${theme}`}>
<h1>{locale.greeting}, {user.name}</h1>
</div>
);
}
A escolha entre useContext e Redux depende da escala e complexidade do gerenciamento de estado. useContext + useReducer é uma substituição leve para o Redux em aplicações pequenas e médias. Não requer instalação de biblioteca externa, é mais fácil de aprender e é suficiente para a maioria das tarefas. O Redux é justificado quando uma arquitetura rigorosa com middleware, devtools e atualizações imutáveis é necessária.
A principal vantagem do Redux sobre o useContext é a otimização de re-renderizações. Por padrão, quando o valor em um Provider muda, todos os consumidores do contexto são re-renderizados. O Redux com useSelector e shallowEqual permite que os componentes se inscrevam apenas em partes específicas do estado, o que reduz significativamente o número de re-renderizações em aplicações grandes. O contexto também pode ser otimizado dividindo-o em muitos contextos pequenos.
| Critério | useContext | Redux |
|---|---|---|
| Complexidade | Sem dependências externas | Requer configuração de store e middleware |
| Re-renderizações | Todos os consumidores em qualquer alteração | Apenas os inscritos em um slice específico |
| DevTools | React DevTools | Redux DevTools com viagem no tempo |
| Middleware | Não suportado | Redux Thunk, Saga, Observable |
| Quando escolher | Aplicações médias, 3–5 contextos | Aplicações grandes com lógica de negócio complexa |
De acordo com os Mantenedores do Redux — Quando usar Redux (2024), 70% das aplicações React não precisam de Redux. Se você tem menos de 50 componentes e o estado não envolve lógica complexa com cache, debounce e efeitos colaterais — useContext + useReducer é mais que suficiente. O Redux adiciona boilerplate e deve ser usado de forma consciente.
O erro mais comum é recriar o objeto value em cada renderização do Provider. Se você passar value={{ user, login }} para o Provider, um novo objeto é criado em cada renderização do Provider, fazendo com que todos os consumidores sejam re-renderizados mesmo que os dados não tenham mudado. A solução é memorizar o valor com useMemo ou usar contextos separados para dados que mudam com frequência e raramente.
// ❌ Novo objeto em cada renderização — todos os consumidores re-renderizam
<AuthContext.Provider value={{ user, login }}>{children}</AuthContext.Provider>
// ✅ Valor memorizado — re-renderiza apenas quando user ou login muda
const authValue = useMemo(() => ({ user, login }), [user, login]);
<AuthContext.Provider value={authValue}>{children}</AuthContext.Provider>
Para resolver o problema do “contexto grande”, divida o estado global em grupos lógicos: AuthContext, ThemeContext, I18nContext. Cada contexto é responsável pela sua própria área e atualiza-se independentemente. Isso é mais simples do que tentar otimizar um contexto gigante através de useMemo e oferece um comportamento de re-renderização mais previsível.
Perguntas frequentes
Sim, se você passar uma função mutadora no value do Provider. O padrão típico é armazenar o estado no Provider e passar tanto os dados quanto as funções de atualização através do useContext. Os componentes filhos chamam essas funções, e a alteração do estado no Provider atualiza automaticamente todos os consumidores. É uma substituição básica do Redux para aplicações pequenas.
Para cenários simples, useContext é mais rápido devido à ausência de overhead do store e middleware. Mas com atualizações frequentes e muitos consumidores, o Redux vence porque seus seletores (useSelector) subscrevem-se a partes específicas do estado, enquanto o useContext re-renderiza todos os consumidores em qualquer alteração. Para aplicações com alta frequência de atualizações (animações, tempo real), escolha Redux ou bibliotecas especializadas.
Não. useContext, como todos os hooks, só pode ser chamado dentro de um componente funcional React ou de um hook personalizado. Se precisar obter o valor do contexto numa função normal (por exemplo, numa utilidade ou serviço), passe-o como parâmetro a partir do componente ou use um módulo separado com estado global fora do React.
A tipagem do contexto no TypeScript é feita especificando o tipo no createContext: createContext<AuthContextType | null>(null). Isto garante que useContext(AuthContext) retorna um valor do tipo correto. Um padrão conveniente é criar um hook personalizado useAuth que chama useContext, verifica se é null e lança um erro claro: “useAuth deve ser usado dentro de AuthProvider”.
A razão mais comum é que o componente consumidor não está dentro do Provider correspondente. Verifique se o Provider envolve toda a subárvore onde useContext é usado. A segunda razão — foi passado um objeto de contexto diferente para o Provider: o desenvolvedor cria um contexto com createContext mas usa useContext com uma instância diferente de createContext.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também