How to use async function in React hooks useEffect (Typescript/JS)?

Andréas Hanss
Oct 18, 2019 · 2 min read
Image for post
Image for post

👾At first glance, you could have the idea to do something similar to get your content from a remote API as an example.

const MyFunctionnalComponent: React.FC = (props) => {
useEffect(async () => {
await loadContent();
}, []);
return <div></div>;
}

If you’re using Typescript, the compiler should be yielding something like this :

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

Let’s see why this error appears by taking the definition of what an async function is:

A function that allows to use asynchronous instructions with the await keyword which will block the statement execution as long as the Promise after which the await keyword is doesn’t resolve…

All right seems great… but wait…

This function will also return a Promise, no matter if you explicitly return something or not. In case you return data, it will be wrapped in the resolving content of the promise that the function will create and return automatically.

Huh! Did you start seeing the problem here? No? Let’s read about the useEffect hook here to get more information: https://reactjs.org/docs/hooks-reference.html#useeffect

Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to useEffect may return a clean-up function. For example, to create a subscription.

📌 Using an async function makes the callback function return a Promise instead of a cleanup function.

And that’s why the compiler is yielding in Typescript. This pattern is also not working in plain JS as React is not waiting for a promise.

By using the following technique, we will be able to use async function in our effects :

const MyFunctionnalComponent: React.FC = props => {
useEffect(() => {
// Create an scoped async function in the hook
async function anyNameFunction() {
await loadContent();
}
// Execute the created function directly
anyNameFunction();
}, []);
return <div></div>;
};

Now, your code is safe as you are returning nothing at all and the compiler has stopped yielding.

🎬 Bonus / TLDR; 📦

You can also use an IIFE, which has the same effect as above.

If you don’t know what an IIFE is: it is described here by my Friend Sunil Sandhu.

const MyFunctionnalComponent: React.FC = props => {
useEffect(() => {
// Using an IIFE
(async function anyNameFunction() {
await loadContent();
})();
}, []);
return <div></div>;
};

🇫🇷STOP! Are you French 🥖 ? Alors tu devrais plutôt cliquer ici pour recevoir ma newsletter privée en Français 🙂

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Andréas Hanss

Written by

⚡️ Andréas HANSS — 👨🏻‍💻Javascript’ Tech Lead 🇫🇷 — react | react-native | modern js |🔥 Firebase — https://linktr.ee/scr34mz — Passionated about learning.

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Andréas Hanss

Written by

⚡️ Andréas HANSS — 👨🏻‍💻Javascript’ Tech Lead 🇫🇷 — react | react-native | modern js |🔥 Firebase — https://linktr.ee/scr34mz — Passionated about learning.

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store