Next.js stability

no-async-useeffect

Disallow `useEffect(async () => …)` — returns a Promise instead of a cleanup.

The single most common AI-generated React antipattern. An async callback returns `Promise<undefined>`, which React does not treat as a cleanup. Subscriptions leak; React 18 Strict Mode's double-invoke produces races that look impossible to reproduce. Wrap the async body in an inner function and call it.

Behavior

  • Fixable: No.
  • Suggestions: No.

Examples

Bad:

useEffect(async () => { await load(); }, []);

Good:

useEffect(() => { (async () => { await load(); })(); }, []);

Related rules

Use it

Enable no-async-useeffect in your eslint.config.js:

import deslint from '@deslint/eslint-plugin';

export default [
  {
    plugins: { deslint },
    rules: {
      'deslint/no-async-useeffect': 'error',
    },
  },
];

Found a false positive? Report it on GitHub →

Back to all rules