diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js index 7b90afb75a742..296f001cc7a55 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js @@ -1042,6 +1042,22 @@ const tests = { `, errors: [classError('useState')], }, + { + code: normalizeIndent` + async function AsyncComponent() { + useState(); + } + `, + errors: [asyncComponentHookError('useState')], + }, + { + code: normalizeIndent` + async function AsyncComponent() { + use(); + } + `, + errors: [asyncComponentHookError('use')], + }, ], }; @@ -1368,6 +1384,12 @@ function useEffectEventError(fn) { }; } +function asyncComponentHookError(fn) { + return { + message: `React Hook "${fn}" cannot be called in an async function.`, + }; +} + // For easier local testing if (!process.env.CI) { let only = []; diff --git a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js b/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js index e6a71cec116b0..c5dbb68c58969 100644 --- a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js +++ b/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js @@ -485,6 +485,16 @@ export default { // Pick a special message depending on the scope this hook was // called in. if (isDirectlyInsideComponentOrHook) { + const isAsyncFunction = codePathNode.async; + if (isAsyncFunction) { + context.report({ + node: hook, + message: + `React Hook "${context.getSource(hook)}" cannot be ` + + 'called in an async function.', + }); + } + // Report an error if a hook does not reach all finalizing code // path segments. //