69

Why can't useEffect() use async-await?

const Home: React.FC = () => {
    
    useEffect(async () => {
        console.log(await ecc.randomKey())
    }, [])
    
    return (
    ...

The error I get is

Argument of type '() => Promise' is not assignable to parameter of type 'EffectCallback'.

Type 'Promise' is not assignable to type 'void | (() => void | undefined)'.

Type 'Promise' is not assignable to type '() => void | undefined'.

Type 'Promise' provides no match for the signature '(): void | undefined'.ts(2345)

Lin Du
  • 88,126
  • 95
  • 281
  • 483
Bill
  • 4,614
  • 13
  • 77
  • 132

3 Answers3

81

Declaring the effect as async function is not recommended. But you can call async functions within the effect like following:

useEffect(() => {
  const genRandomKey = async () => {
    console.log(await ecc.randomKey())
  };

  genRandomKey();
}, []);

More here: React Hooks Fetch Data

Tobias Lins
  • 2,543
  • 19
  • 22
  • 3
    Be careful doing this.... async callbacks after await could return after a react component has been dismounted and if you touch any component state in that scenario react will crash and throw some nasty errors. Anytime you are doing async things in a useEffect etc you should be checking if the component has unmounted before touching state. – Ryan Mann Apr 16 '22 at 06:59
  • 1
    I'm getting an IDE warning saying Promise returned from asyncMethod is ignored. Is this mechanism really safe? – Liam Clark Gutiérrez Jun 25 '22 at 12:44
37

You can use an IIFE (asynchronous anonymous function which executes itself) like so:

useEffect(() => {
    // Some synchronous code.

    (async () => {
        await doSomethingAsync();
    })();

    return () => {
        // Component unmount code.
    };
}, []);
Daniel
  • 8,655
  • 5
  • 60
  • 87
  • 2
    For those who don't know what it's called, it is IIFE (Immediately Invoked Function Expression) and here's the MDN link https://developer.mozilla.org/en-US/docs/Glossary/IIFE – Badmaash Sep 17 '21 at 16:57
1

You can use the use-async-effect package which provides a useAsyncEffect hook:

useAsyncEffect(async () => {
  await doSomethingAsync();
});
Daniel
  • 8,655
  • 5
  • 60
  • 87