fix(compiler): recognize 'use' as a hook for hook detection#704
fix(compiler): recognize 'use' as a hook for hook detection#704
Conversation
React's 'use()' API is a hook for reading context and promises,
but the compiler's isHookName() function only matched 'use[A-Z0-9]'
pattern, causing custom hooks that only call use() to be silently
skipped during compilation.
This fix adds 'use' to the hook name recognition so that functions
like:
function useMyContext() {
return use(MyContext);
}
will now be correctly compiled with memoization.
Fixes #35960
Greptile SummaryThis PR mirrors facebook/react#36028 and fixes a bug where custom hooks that only call React's However, there is a material inconsistency left behind:
Confidence Score: 3/5
Important Files Changed
Prompt To Fix All With AIThis is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts
Line: 898
Comment:
**Sibling `isHookName` in `Environment.ts` not updated**
There is a second, independently-defined `isHookName` exported from `compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts` (line 1037) that still uses only the old regex:
```ts
// Environment.ts – unchanged
export function isHookName(name: string): boolean {
return /^use[A-Z0-9]/.test(name);
}
```
This exported function is the one actually used throughout the HIR pipeline – `ValidateHooksUsage.ts`, `Globals.ts`, and `Imports.ts` all import it. Because it was not updated, identifiers named exactly `'use'` are not treated as hook names inside compilation:
1. **`Globals.ts` (line 1027)** — When a user-supplied type provider configures a function called `'use'` as a hook, `isHookName('use')` returns `false` but the type check returns `true`, triggering a spurious `CompilerError.throwInvalidConfig`.
2. **`Environment.ts` (line 858 / 897)** — For non-React third-party imports whose name is `'use'`, the fallback `isHookName` check will not assign the custom hook type.
3. **`ValidateHooksUsage.ts` (lines 168, 197)** — Hook-usage validation based on identifier names will miss identifiers named `'use'`.
The comment on `Environment.ts`'s `isHookName` explicitly says it mirrors the eslint-plugin-react-hooks implementation, and that source (`eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts` line 30) has *already* been updated to `s === 'use' || /^use[A-Z0-9]/.test(s)`. The same update should be applied here:
```ts
// Environment.ts
export function isHookName(name: string): boolean {
return name === 'use' || /^use[A-Z0-9]/.test(name);
}
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: 7af1c89 |
|
|
||
| function isHookName(s: string): boolean { | ||
| return /^use[A-Z0-9]/.test(s); | ||
| return s === 'use' || /^use[A-Z0-9]/.test(s); |
There was a problem hiding this comment.
Sibling isHookName in Environment.ts not updated
There is a second, independently-defined isHookName exported from compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts (line 1037) that still uses only the old regex:
// Environment.ts – unchanged
export function isHookName(name: string): boolean {
return /^use[A-Z0-9]/.test(name);
}This exported function is the one actually used throughout the HIR pipeline – ValidateHooksUsage.ts, Globals.ts, and Imports.ts all import it. Because it was not updated, identifiers named exactly 'use' are not treated as hook names inside compilation:
Globals.ts(line 1027) — When a user-supplied type provider configures a function called'use'as a hook,isHookName('use')returnsfalsebut the type check returnstrue, triggering a spuriousCompilerError.throwInvalidConfig.Environment.ts(line 858 / 897) — For non-React third-party imports whose name is'use', the fallbackisHookNamecheck will not assign the custom hook type.ValidateHooksUsage.ts(lines 168, 197) — Hook-usage validation based on identifier names will miss identifiers named'use'.
The comment on Environment.ts's isHookName explicitly says it mirrors the eslint-plugin-react-hooks implementation, and that source (eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts line 30) has already been updated to s === 'use' || /^use[A-Z0-9]/.test(s). The same update should be applied here:
// Environment.ts
export function isHookName(name: string): boolean {
return name === 'use' || /^use[A-Z0-9]/.test(name);
}Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts
Line: 898
Comment:
**Sibling `isHookName` in `Environment.ts` not updated**
There is a second, independently-defined `isHookName` exported from `compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts` (line 1037) that still uses only the old regex:
```ts
// Environment.ts – unchanged
export function isHookName(name: string): boolean {
return /^use[A-Z0-9]/.test(name);
}
```
This exported function is the one actually used throughout the HIR pipeline – `ValidateHooksUsage.ts`, `Globals.ts`, and `Imports.ts` all import it. Because it was not updated, identifiers named exactly `'use'` are not treated as hook names inside compilation:
1. **`Globals.ts` (line 1027)** — When a user-supplied type provider configures a function called `'use'` as a hook, `isHookName('use')` returns `false` but the type check returns `true`, triggering a spurious `CompilerError.throwInvalidConfig`.
2. **`Environment.ts` (line 858 / 897)** — For non-React third-party imports whose name is `'use'`, the fallback `isHookName` check will not assign the custom hook type.
3. **`ValidateHooksUsage.ts` (lines 168, 197)** — Hook-usage validation based on identifier names will miss identifiers named `'use'`.
The comment on `Environment.ts`'s `isHookName` explicitly says it mirrors the eslint-plugin-react-hooks implementation, and that source (`eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts` line 30) has *already* been updated to `s === 'use' || /^use[A-Z0-9]/.test(s)`. The same update should be applied here:
```ts
// Environment.ts
export function isHookName(name: string): boolean {
return name === 'use' || /^use[A-Z0-9]/.test(name);
}
```
How can I resolve this? If you propose a fix, please make it concise.
Mirror of facebook/react#36028
Original author: MorikawaSouma
Summary
React's \use()\ API is a hook for reading context and promises, but the compiler's \isHookName()\ function only matched the \use[A-Z0-9]\ pattern, causing custom hooks that only call \use()\ to be silently skipped during compilation.
Problem
When a custom hook only contains a \use()\ call:
\\js
function useMyContext() {
return use(MyContext);
}
\\
The compiler would skip this function because \use\ does not match /^use[A-Z0-9]/. This resulted in no memoization being applied.
Solution
Add 'use'\ to the hook name recognition in \isHookName()\ so that \use()\ is correctly identified as a hook call.
Test Plan
Verified by checking that:
Fixes #35960