react icon indicating copy to clipboard operation
react copied to clipboard

[Compiler Bug]: False positive on "Hooks may not be referenced as normal values, they must be called"

Open oliverlaz opened this issue 1 month ago • 1 comments

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

oliverlaz avatar Dec 08 '25 14:12 oliverlaz

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

  1. 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.

  1. Não colocar hooks diretamente em objetos com nomes começando em use const hooks = { value: useValue };

  2. Criar wrappers, se quiser mais organização const getValue = () => useValue();

LC-cristofer avatar Dec 08 '25 17:12 LC-cristofer