# Warning: useEffect must not return anything besides a function, which is used for clean-up. It looks like you wrote useEffect(async () => ...) or returned a Promise.

- **ID:** `react/useeffect-cleanup-return-promise`
- **Domain:** react
- **Category:** runtime_error
- **Verification:** ai_generated
- **Fix Rate:** 92%

## Root Cause

The cleanup function of useEffect must be either undefined or a synchronous function. Returning a Promise (e.g., from an async function) causes this warning because React cannot call .then() on the cleanup.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| React 16.8+ | active | — | — |
| React 17.x | active | — | — |
| React 18.x | active | — | — |

## Workarounds

1. **Define an async function inside useEffect and call it immediately, then return a cleanup function. Example: useEffect(() => { const fetchData = async () => { /* ... */ }; fetchData(); return () => { /* cleanup */ }; }, []);** (95% success)
   ```
   Define an async function inside useEffect and call it immediately, then return a cleanup function. Example: useEffect(() => { const fetchData = async () => { /* ... */ }; fetchData(); return () => { /* cleanup */ }; }, []);
   ```
2. **Use a custom hook like useAsyncEffect from a library (e.g., react-use) that handles async effects properly.** (85% success)
   ```
   Use a custom hook like useAsyncEffect from a library (e.g., react-use) that handles async effects properly.
   ```
3. **For simple cases, use .then() and .catch() instead of async/await: useEffect(() => { fetch('/data').then(setData).catch(handleError); return () => { /* cleanup */ }; }, []);** (90% success)
   ```
   For simple cases, use .then() and .catch() instead of async/await: useEffect(() => { fetch('/data').then(setData).catch(handleError); return () => { /* cleanup */ }; }, []);
   ```

## Dead Ends

- **** — The async function still returns a Promise, which React interprets as an invalid cleanup return value. (90% fail)
- **** — Promise.resolve() returns a Promise, still violating the rule that cleanup must be a function or undefined. (85% fail)
- **** — The return value of the async function is a Promise, regardless of wrapping. (80% fail)
