rules-of-hooks
Valida se os componentes e hooks seguem as Regras dos Hooks.
Detalhes da Regra
O React depende da ordem em que os hooks são chamados para preservar corretamente o estado entre as renderizações. Cada vez que seu componente é renderizado, o React espera que os mesmos hooks sejam chamados na mesma ordem. Quando os hooks são chamados condicionalmente ou em loops, o React perde o controle de qual estado corresponde a qual chamada de hook, levando a bugs como inconsistências de estado e erros de “Rendered fewer/more hooks than expected”.
Violações Comuns
Estes padrões violam as Regras dos Hooks:
- Hooks em condições (
if/else, ternário,&&/||) - Hooks em loops (
for,while,do-while) - Hooks após retornos antecipados
- Hooks em callbacks/manipuladores de eventos
- Hooks em funções assíncronas
- Hooks em métodos de classe
- Hooks no nível do módulo
Inválido
Exemplos de código incorreto para esta regra:
// ❌ Hook em condição
if (isLoggedIn) {
const [user, setUser] = useState(null);
}
// ❌ Hook após retorno antecipado
if (!data) return <Loading />;
const [processed, setProcessed] = useState(data);
// ❌ Hook em callback
<button onClick={() => {
const [clicked, setClicked] = useState(false);
}}/>
// ❌ `use` em try/catch
try {
const data = use(promise);
} catch (e) {
// tratamento de erro
}
// ❌ Hook no nível do módulo
const globalState = useState(0); // Fora do componenteVálido
Exemplos de código correto para esta regra:
function Component({ isSpecial, shouldFetch, fetchPromise }) {
// ✅ Hooks no nível superior
const [count, setCount] = useState(0);
const [name, setName] = useState('');
if (!isSpecial) {
return null;
}
if (shouldFetch) {
// ✅ `use` pode ser condicional
const data = use(fetchPromise);
return <div>{data}</div>;
}
return <div>{name}: {count}</div>;
}Solução de Problemas
Quero buscar dados com base em alguma condição
Você está tentando chamar useEffect condicionalmente:
// ❌ Hook condicional
if (isLoggedIn) {
useEffect(() => {
fetchUserData();
}, []);
}Chame o hook incondicionalmente, verifique a condição dentro dele:
// ✅ Condição dentro do hook
useEffect(() => {
if (isLoggedIn) {
fetchUserData();
}
}, [isLoggedIn]);Preciso de estados diferentes para cenários diferentes
Você está tentando inicializar o estado condicionalmente:
// ❌ Estado condicional
if (userType === 'admin') {
const [permissions, setPermissions] = useState(adminPerms);
} else {
const [permissions, setPermissions] = useState(userPerms);
}Sempre chame useState, defina o valor inicial condicionalmente:
// ✅ Valor inicial condicional
const [permissions, setPermissions] = useState(
userType === 'admin' ? adminPerms : userPerms
);Opções
Você pode configurar hooks de efeito personalizados usando configurações compartilhadas do ESLint (disponíveis no eslint-plugin-react-hooks 6.1.1 e posterior):
{
"settings": {
"react-hooks": {
"additionalEffectHooks": "(useMyEffect|useCustomEffect)"
}
}
}additionalEffectHooks: Padrão Regex que corresponde a hooks personalizados que devem ser tratados como efeitos. Isso permite queuseEffectEvente funções de evento semelhantes sejam chamados a partir de seus hooks de efeito personalizados.
Esta configuração compartilhada é usada pelas regras rules-of-hooks e exhaustive-deps, garantindo um comportamento consistente em toda a verificação de linting relacionada a hooks.