🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Como consertar o React Hook useState é chamado de erro condicional

⏱️5 min read  ·  905 words

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.

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

  1. Chame apenas ganchos no nível superior — nunca dentro de condições, loops ou funções aninhadas. Sempre na mesma ordem.
  2. Chame apenas ganchos de funções React — Componentes React ou ganchos personalizados (funções começando comuse). 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.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা