Skip to content

Commit 9916265

Browse files
committed
[ESLint] Allow useId in async functions
`useId` is the only Hook allowed in React Server Components so it should be allowed in async functions.
1 parent 0911120 commit 9916265

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,21 @@ const tests = {
550550
// TODO: this should error but doesn't.
551551
// errors: [genericError('useState')],
552552
},
553+
{
554+
code: normalizeIndent`
555+
async function Page() {
556+
useId();
557+
React.useId();
558+
}
559+
`,
560+
},
561+
{
562+
code: normalizeIndent`
563+
async function useAsyncHook() {
564+
useId();
565+
}
566+
`,
567+
},
553568
],
554569
invalid: [
555570
{
@@ -1129,6 +1144,14 @@ const tests = {
11291144
`,
11301145
errors: [asyncComponentHookError('useState')],
11311146
},
1147+
{
1148+
code: normalizeIndent`
1149+
async function notAHook() {
1150+
useId();
1151+
}
1152+
`,
1153+
errors: [functionError('useId', 'notAHook')],
1154+
},
11321155
{
11331156
code: normalizeIndent`
11341157
Hook.use();

packages/eslint-plugin-react-hooks/src/RulesOfHooks.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@ function isHook(node) {
4040
}
4141
}
4242

43+
const serverComponentHooks = new Set(['useId']);
44+
function isServerComponentHook(node) {
45+
if (node.type === 'Identifier') {
46+
return serverComponentHooks.has(node.name);
47+
} else if (
48+
node.type === 'MemberExpression' &&
49+
!node.computed &&
50+
node.property.type === 'Identifier'
51+
) {
52+
return serverComponentHooks.has(node.property.name);
53+
} else {
54+
return false;
55+
}
56+
}
57+
4358
/**
4459
* Checks if the node is a React component name. React component names must
4560
* always start with an uppercase letter.
@@ -504,7 +519,7 @@ export default {
504519
if (isDirectlyInsideComponentOrHook) {
505520
// Report an error if the hook is called inside an async function.
506521
const isAsyncFunction = codePathNode.async;
507-
if (isAsyncFunction) {
522+
if (isAsyncFunction && !isServerComponentHook(hook)) {
508523
context.report({
509524
node: hook,
510525
message:

0 commit comments

Comments
 (0)