Skip to content

Commit bc484bd

Browse files
committed
[ESLint] Disallow hooks in async functions
Hooks cannot be called in async functions, on either the client or the server. This mistake sometimes happens when using Server Components, especially when refactoring a Server Component to a Client Component. React logs a warning at runtime, but it's even better to catch this with a lint rule since it will show immediate inline feedback in the editor. I added this to the existing "Rules of Hooks" ESLint rule.
1 parent 53ac219 commit bc484bd

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,22 @@ const tests = {
10421042
`,
10431043
errors: [classError('useState')],
10441044
},
1045+
{
1046+
code: normalizeIndent`
1047+
async function AsyncComponent() {
1048+
useState();
1049+
}
1050+
`,
1051+
errors: [asyncComponentHookError('useState')],
1052+
},
1053+
{
1054+
code: normalizeIndent`
1055+
async function useAsyncHook() {
1056+
useState();
1057+
}
1058+
`,
1059+
errors: [asyncComponentHookError('useState')],
1060+
},
10451061
],
10461062
};
10471063

@@ -1300,6 +1316,14 @@ if (__EXPERIMENTAL__) {
13001316
`,
13011317
errors: [classError('use')],
13021318
},
1319+
{
1320+
code: normalizeIndent`
1321+
async function AsyncComponent() {
1322+
use();
1323+
}
1324+
`,
1325+
errors: [asyncComponentHookError('use')],
1326+
},
13031327
];
13041328
}
13051329

@@ -1368,6 +1392,12 @@ function useEffectEventError(fn) {
13681392
};
13691393
}
13701394

1395+
function asyncComponentHookError(fn) {
1396+
return {
1397+
message: `React Hook "${fn}" cannot be called in an async function.`,
1398+
};
1399+
}
1400+
13711401
// For easier local testing
13721402
if (!process.env.CI) {
13731403
let only = [];

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,17 @@ export default {
485485
// Pick a special message depending on the scope this hook was
486486
// called in.
487487
if (isDirectlyInsideComponentOrHook) {
488+
// Report an error if the hook is called inside an async function.
489+
const isAsyncFunction = codePathNode.async;
490+
if (isAsyncFunction) {
491+
context.report({
492+
node: hook,
493+
message:
494+
`React Hook "${context.getSource(hook)}" cannot be ` +
495+
'called in an async function.',
496+
});
497+
}
498+
488499
// Report an error if a hook does not reach all finalizing code
489500
// path segments.
490501
//

0 commit comments

Comments
 (0)