(Solved) Argument of type ‘() => Promise’ is not assignable to parameter of type ‘EffectCallback’

I’ve been using useEffect hooks heavily since React introduced them in version 16.8. A way to think of Effect hooks is like React lifecycle method (componentDidMount, componentDidUpdate, componentDWillUnmount) bundled into one function, or hook as React defines it to perform side effects in function components.

Recently I came across the error Argument of type ‘() => Promise’ is not assignable to parameter of type ‘EffectCallback’. Type ‘Promise’ is not assignable to type ‘void | (() => void) after attempting to run asynchronous code (async and await) inside the callback function of useEffect hook.

Screenshot of the code showing the error Argument of type ‘() => Promise’ is not assignable to parameter of type ‘EffectCallback’. Type ‘Promise’ is not assignable to type ‘void | (() => void)

There are two ways to solve prevent getting the error Argument of type ‘() => Promise’ is not assignable to parameter of type ‘EffectCallback’. Type ‘Promise’ is not assignable to type ‘void | (() => void):

  1. Define an async function inside the useEffect hook
  2. Define an IIFE inside the useEffect hook

Solution #1 – Define an async function inside the useEffect hook

For this first solution, instead of using the async and await keywords to run asynchronous code inside the useEffect, which is like the following piece of code,

import React, { useEffect } from 'react';

const MyComponent = () => {
  useEffect(async () => {
    const res = await fetch('https://randomuser.me/api/');
      const data = await res.json();
      const user = data.results?.[0];
      
     console.log(user);
  });

  return <div>Hello World!</div>;
};

export default MyComponent;

you need to define an async function inside the callback function and execute that function inside the useEffect hook. Below is an example of what I’m referring:

import React, { useEffect } from 'react';

const MyComponent = () => {
  useEffect(() => {
    const fetchUser = async () => {
      const res = await fetch('https://randomuser.me/api/');
      const data = await res.json();
      const user = data.results?.[0];
      
      return user;
    } 

    fetchUser();
  });

  return <div>Hello World!</div>;
};

export default MyComponent;

If you compare the previous two snippets of code, notice how the second snippet doesn’t define the useEffect callback function as async.

Instead, an anonymous function is defined inside the useEffect callback function and assigned to the variable fetchUser. That anonymous function uses the async and await keywords, enabling promised-based behavior. Finally, the fetchUser function variable is executed. In that way, you can still run asynchronous logic inside useEffect hooks.

Solution #2 – Define an IIFE inside the useEffect hook

The second solution is very similar to the previous solution. However, instead of defining an anonymous function inside the useEffect callback function, you will need to execute an IIFE or Immediately Invoked Function Expression.

An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.

MDN Web Docs

Take a look at how I use IIFE inside the useEffect hook callback function to run promise-based asynchronous code.

import React, { useEffect } from 'react';

const MyComponent = () => {
  useEffect(() => {
    (async () => {
      const res = await fetch('https://randomuser.me/api/');
      const data = await res.json();
      const user = data.results?.[0];
      
      return user;
    })();
  });

  return <div>Hello World!</div>;
};

export default MyComponent;