Code Buckets

Buckets of code


Better Async Calls in the useEffect Hook

useEffect hook lifecycle
useEffect lifecycle. The component mounts then renders. The useEffect call is triggered after mount.

The useEffect hook allows you to perform side effects on your React page. A common use case would be to perform an API call to populate the page when the page has mounted i.e.

  useEffect(async () => {
    const data await callApi();
    //.. now populate the page

The Problem

The callApi method is long running, so async and it doesn’t block the thread. However we can’t put async methods into useEffect. It can cause race conditions so it’s not allowed. Our IDE will complain and the code won’t run.


Just embed an async method into your useEffect hook and call it i.e.

  useEffect(() => {
    const loadData = async () => {
        await callApi();
        //.. now populate page

That does work and we can have an async call in the useEffect hook.

A Better Solution

The reason I’m writing the post is because I saw a neater solution to this on a training video. Just use an immediately invoked function expressions to define and call the async method in one code block. So the solution now becomes

useEffect(() => {
    (async () => {
        await callApi();
        //.. now populate page

I’ve defined and executed the async method in one block and I don’t have a spurious loadData method. A lot neater I think.

Useful Links
Official documentation about the useEffect hook
Mozilla on immediately invoked function expressions. I used to use IIFE all the time – they were a bit of a standard. So I was pleased to dust them off and use them to tidy up some the code.  I always thought they were neat and gave your code that sheen of cleverness that we all love.
The diagram was drawn with Mermaid which is a bit of a go to drawing tool for me right now.


Your email address will not be published. Required fields are marked *