[Compiler Bug]: False positive on "Hooks may not be referenced as normal values, they must be called"
What kind of issue is this?
- [ ] React Compiler core (the JS output is incorrect, or your app works incorrectly after optimization)
- [x] babel-plugin-react-compiler (build issue installing or using the Babel plugin)
- [ ] eslint-plugin-react-hooks (build issue installing or using the eslint plugin)
- [ ] react-compiler-healthcheck (build issue installing or using the healthcheck script)
Link to repro
https://playground.react.dev/#N4Igzg9grgTgxgUxALhHCA7MAXABFMBANQEMAbKBXAXlwAoBKGgPn0IFkEBbCOxl3ABYATABpcAbQC6DANwAdDOix4AFhAgBrMDVzA2xcpVwBfBRkXKcuAGIkAlmR21+1VsEW5cVvPoKGKKhNddS0wcy8fXAA3Iypaf1JAxgjcGARsWAxcAB4wAAcSDGZgWMCTHIB6AqLmRRNFS0xrAHUIGG1dV3dPb2bfAyTKZBjTEI1tVKiy41polN70zJhsvMLi0riK6vW6jAaMEFE0TAAzewBzFBB7Lnz2vGwAT3yqfQAFCgv7DAB5fOw9maY1OMAgXFwAHIAEYkaEIMgAWnyXx+iPSJDg2ER6DujgQMEqABN7DhIeZFHQPPtcGASICwOcEDpPlBvn8AUCsHIjuB1AB3ACSGGwBIw5DAKFOEoQJiAA
Repro steps
The React Compiler doesn't correctly flag improper hook usage, when using a "hooks provider". Although the hook is always called, React Compiler fails with the following message:
Hooks may not be referenced as normal values, they must be called.
It seems the fact that the hook variable name starts with use_ is causing the compiler assume its usage.
const useValue = () => useMemo(() => 42, []);
const hooks = { useValue };
const Fails = () => {
const { useValue } = hooks;
const value = useValue();
// ^^^^^^^^ Hooks may not be referenced as normal values, they must be called.
return <span>{value}</span>
}
const Works = () => {
const { useValue: v } = hooks;
const value = v(); // works as expected
return <span>{value}</span>
}
How often does this bug happen?
Every time
What version of React are you using?
19.2.1
What version of React Compiler are you using?
1.0.0
RESUMO DO PROBLEMA
Quando você coloca um hook dentro de um objeto e desestrutura ele mantendo o nome que começa com use:
const { useValue } = hooks; const value = useValue();
o React Compiler acusa erro, dizendo:
Hooks may not be referenced as normal values, they must be called.
Mesmo que você esteja de fato chamando o hook dentro do componente. Se você renomeia:
const { useValue: v } = hooks;
o erro some. Ou seja, o problema é puramente o nome da variável.
POR QUE ISSO ACONTECE
O React Compiler (React 19) usa análise estática extremamente agressiva para detectar violações das Regras dos Hooks.
Ele se baseia em duas coisas:
Fluxo de execução do componente
Nomes das funções/variáveis
E aí vem o bug: Se uma variável começa com use, o compilador assume automaticamente:
“isso é um hook”
“hooks não podem ser referenciados como valores”
“só podem ser chamados diretamente no corpo do componente”
Então quando ele vê:
const { useValue } = hooks;
ele acha que você está:
Pegando um hook por referência
Guardando hook dentro de objetos
Violando as regras
Mesmo que nada disso seja verdade.
Ele não vê a intenção real. Ele só vê o nome da variável e reage como um alarme de carro mal regulado.
Por isso renomear funciona: tirou o use, o compilador para de enxergar aquilo como hook e aceita.
SOLUÇÃO
- Renomear na desestruturação (solução mais simples e recomendada) const { useValue: getValue } = hooks; const value = getValue();
Isso já evita que o compilador confunda a função com um hook.
-
Não colocar hooks diretamente em objetos com nomes começando em use const hooks = { value: useValue };
-
Criar wrappers, se quiser mais organização const getValue = () => useValue();