O erroReact Hook “useState” é chamado condicionalmente. React Hooks devem ser chamados exatamente na mesma ordem em cada renderização de componente é um dos erros mais comuns do React. Isso viola as regras dos ganchos. Veja por que isso acontece e como corrigir cada variante.
📋 Table of Contents
- Por que esta regra existe
- O Código Quebrado
- Correção 1: Chame os ganchos primeiro, condicione depois
- Correção 2: gancho dentro de um bloco de condição
- Correção 3: gancho dentro de um laço
- Correção 4: Gancho após um retorno antecipado
- As duas regras dos ganchos
- Manipulando Lógica Condicional Corretamente
- Aplique as regras com ESLint
- Perguntas Frequentes
- Conclusão
Por que esta regra existe
O React rastreia ganchos por seuordem de chamada, não pelo nome. Em cada renderização, o React espera os mesmos ganchos na mesma sequência. Se um gancho estiver dentro de uma condição, ele poderá ser executado em uma renderização, mas não na próxima — quebrando o rastreamento interno do React e fazendo com que o estado seja atribuído ao gancho errado.
O Código Quebrado
// 🐛 Hook inside a condition — VIOLATES rules of hooks
function Profile({ userId }) {
if (!userId) {
return <div>No user</div>; // early return BEFORE hooks
}
const [user, setUser] = useState(null); // ❌ conditionally called
// If userId is falsy, this hook is skipped — breaks React's tracking
return <div>{user?.name}</div>;
}
Correção 1: Chame os ganchos primeiro, condicione depois
// ✅ All hooks at the top, unconditionally
function Profile({ userId }) {
const [user, setUser] = useState(null); // always called
// Conditional logic AFTER all hooks
if (!userId) {
return <div>No user</div>;
}
return <div>{user?.name}</div>;
}
Correção 2: gancho dentro de um bloco de condição
// 🐛 useEffect inside an if
function Component({ isActive }) {
if (isActive) {
useEffect(() => { // ❌ conditional hook
console.log('active');
}, []);
}
}
// ✅ Move the condition INSIDE the hook
function Component({ isActive }) {
useEffect(() => {
if (isActive) { // condition inside the hook
console.log('active');
}
}, [isActive]);
}
Correção 3: gancho dentro de um laço
// 🐛 Hook in a loop — order changes if items.length changes
function List({ items }) {
return items.map(item => {
const [selected, setSelected] = useState(false); // ❌ in a loop
return <Item key={item.id} />;
});
}
// ✅ Extract into a child component — each has its own hooks
function List({ items }) {
return items.map(item => <Item key={item.id} item={item} />);
}
function Item({ item }) {
const [selected, setSelected] = useState(false); // ✅ top level of component
return <div onClick={() => setSelected(!selected)}>{item.name}</div>;
}
Correção 4: Gancho após um retorno antecipado
// 🐛 Hook after a conditional return
function Widget({ data }) {
const [count, setCount] = useState(0);
if (!data) return null; // early return
const [name, setName] = useState(''); // ❌ never reached when !data
return <div>{name}: {count}</div>;
}
// ✅ ALL hooks before ANY conditional return
function Widget({ data }) {
const [count, setCount] = useState(0);
const [name, setName] = useState(''); // moved up
if (!data) return null; // early return AFTER all hooks
return <div>{name}: {count}</div>;
}
As duas regras dos ganchos
- Chame apenas ganchos no nível superior — nunca dentro de condições, loops ou funções aninhadas. Sempre na mesma ordem.
- Chame apenas ganchos de funções React — Componentes React ou ganchos personalizados (funções começando com
use). Não de funções regulares de JavaScript.
Manipulando Lógica Condicional Corretamente
function Dashboard({ user, showStats }) {
// ✅ Always call all hooks unconditionally
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Conditions go INSIDE the hook, not around it
if (showStats) {
fetchStats().then(setData).finally(() => setLoading(false));
} else {
setLoading(false);
}
}, [showStats]);
// Conditional RENDERING is fine — it's not a conditional hook
if (!user) return <Login />;
if (loading) return <Spinner />;
return showStats ? <Stats data={data} /> : <Overview />;
}
Aplique as regras com ESLint
npm install --save-dev eslint-plugin-react-hooks
// .eslintrc — catches these errors before runtime
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}
Perguntas Frequentes
P: Por que os ganchos não podem ser condicionais? Parece arbitrário.
R: O React identifica os ganchos pela ordem de chamada (primeiro useState, segundo useState, etc.), não pelo nome. Se um gancho às vezes for ignorado, a ordem muda e o React atribui o estado ao gancho errado. A ordem consistente é o que faz os ganchos funcionarem.
P: Posso usar condições dentro de um gancho?
R: Sim! As condições DENTRO de um gancho (dentro do retorno de chamada useEffect, por exemplo) são adequadas. A regra proíbe apenas CHAMAR condicionalmente o próprio gancho.
P: Como executo um efeito condicionalmente?
R: Coloque a condição dentro do corpo do efeito e inclua a variável de condição na matriz de dependência:useEffect(() => { if (cond) {...} }, [cond]).
P: E quanto à renderização condicional – isso é permitido?
R: Sim. A renderização condicional (retornando JSX diferente com base no estado) é perfeitamente adequada, desde que todos os ganchos sejam chamados antes de qualquer retorno condicional. As condições de renderização não são condições de gancho.
P: Posso chamar um gancho personalizado condicionalmente?
R: Não – os ganchos personalizados seguem as mesmas regras, pois chamam os ganchos internamente. Chame-os incondicionalmente no nível superior e coloque condições dentro deles.
Conclusão
O erro “React Hook é chamado condicionalmente” significa que um gancho está dentro de uma condição, loop ou após um retorno antecipado. A correção é sempre a mesma:chame TODOS os ganchos incondicionalmente na parte superior do seu componente, antes de qualquer retorno condicional ou lógica. Coloque condições DENTRO dos ganchos (no corpo do efeito), não ao redor deles. Instalareslint-plugin-react-hooks detectar esses erros automaticamente antes que eles atinjam o tempo de execução — é a melhor proteção contra violações de regras de gancho.
🔗 Share this article
✍️ Leave a Comment