DEV Community

mich0w0h
mich0w0h

Posted on

React: How to tackle useEffect called twice

This is a continuation of this post: React: Blink Character's Eyes - DEV Community

What's the issue

In my React web app, it seemed that the useEffect called twice although I wanted to call a function inside it.

Here's the code.

useEffect(() => {
    blinkWithTimer(3000);
}, []);

const blinkWithTimer = async (timer: number): Promise<void> => {
    const interval = 1500;
    await blinkEyes(1); // One blink
    await delay(interval); // Delay after one blink
    await blinkEyes(2); // Two blinks
    await delay(interval); // Delay after two blinks
    await blinkEyes(1); // One final blink
    setTimeout(() => {
        blinkWithTimer(timer);
    }, timer);
}
Enter fullscreen mode Exit fullscreen mode

What's happening there

It turned out that React 18 runs useEffect twice when it renders the component in the development environment even if the dependency array is empty.

Reference:
How to stop useEffect run twice since React 18

How to tackle this

Regarding my codes, I want to run the blinkWithInterval() only once after the page is loaded.

So this time around, I used useRef valuable and simply checked whether it's already run or not.

const hasMounted = useRef<boolean>(false);
useEffect(() => {
    if(!hasMounted.current) {
        hasMounted.current = true;
        console.log("initialize");
        blinkWithTimer(3000);
    }

    return () => {
        // called when the component is unmounted
    };
}, []);
Enter fullscreen mode Exit fullscreen mode

I read through You Might Not Need an Effect – React but I had no idea how to implement the alternative to above codes without useEffect.

As a result, my requirement of calling blinkWithTimer() only once has been accomplished so I ended this issue here for this time.

Top comments (0)