Regras dos Hooks
Os Hooks são definidos usando funções JavaScript, mas representam um tipo especial de lógica de UI reutilizável com restrições sobre onde podem ser chamados.
Chame Hooks apenas no nível superior
Funções cujos nomes começam com use
são chamadas de Hooks no React.
Não chame Hooks dentro de loops, condições, funções aninhadas ou blocos try
/catch
/finally
. Em vez disso, sempre use Hooks no nível superior da sua função React, antes de quaisquer retornos antecipados. Você só pode chamar Hooks enquanto o React estiver renderizando um componente de função:
- ✅ Chame-os no nível superior no corpo de um componente de função.
- ✅ Chame-os no nível superior no corpo de um Hook personalizado.
function Counter() {
// ✅ Bom: nível superior em um componente de função
const [count, setCount] = useState(0);
// ...
}
function useWindowWidth() {
// ✅ Bom: nível superior em um Hook personalizado
const [width, setWidth] = useState(window.innerWidth);
// ...
}
Não é suportado chamar Hooks (funções que começam com use
) em quaisquer outros casos, por exemplo:
- 🔴 Não chame Hooks dentro de condições ou loops.
- 🔴 Não chame Hooks após uma declaração de
return
condicional. - 🔴 Não chame Hooks em manipuladores de eventos.
- 🔴 Não chame Hooks em componentes de classe.
- 🔴 Não chame Hooks dentro de funções passadas para
useMemo
,useReducer
ouuseEffect
. - 🔴 Não chame Hooks dentro de blocos
try
/catch
/finally
.
Se você quebrar essas regras, pode ver esse erro.
function Bad({ cond }) {
if (cond) {
// 🔴 Ruim: dentro de uma condição (para corrigir, mova para fora!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad() {
for (let i = 0; i < 10; i++) {
// 🔴 Ruim: dentro de um loop (para corrigir, mova para fora!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad({ cond }) {
if (cond) {
return;
}
// 🔴 Ruim: após um return condicional (para corrigir, mova antes do return!)
const theme = useContext(ThemeContext);
// ...
}
function Bad() {
function handleClick() {
// 🔴 Ruim: dentro de um manipulador de evento (para corrigir, mova para fora!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad() {
const style = useMemo(() => {
// 🔴 Ruim: dentro de useMemo (para corrigir, mova para fora!)
const theme = useContext(ThemeContext);
return createStyle(theme);
});
// ...
}
class Bad extends React.Component {
render() {
// 🔴 Ruim: dentro de um componente de classe (para corrigir, escreva um componente de função em vez de uma classe!)
useEffect(() => {})
// ...
}
}
function Bad() {
try {
// 🔴 Ruim: dentro de um bloco try/catch/finally (para corrigir, mova para fora!)
const [x, setX] = useState(0);
} catch {
const [x, setX] = useState(1);
}
}
Você pode usar o eslint-plugin-react-hooks
plugin para capturar esses erros.
Chame Hooks apenas de funções React
Não chame Hooks de funções JavaScript regulares. Em vez disso, você pode:
✅ Chamar Hooks de componentes de função React.
✅ Chamar Hooks de Hooks personalizados.
Seguindo essa regra, você garante que toda a lógica com estado em um componente seja claramente visível a partir do seu código fonte.
function FriendList() {
const [onlineStatus, setOnlineStatus] = useOnlineStatus(); // ✅
}
function setOnlineStatus() { // ❌ Não é um componente ou Hook personalizado!
const [onlineStatus, setOnlineStatus] = useOnlineStatus();
}