0

I simply can't seem to find the bug here? Why does the following code give me a "Cant perform react state update on an unmounted component"?

import React, {useState, useEffect} from 'react'

function LogoText(){
    const[imgCount, setImgCount] = useState(0)
    const imgTexts = [
        "images/logo/LOGO_SDe.svg", 
        "images/logo/LOGO_SRe.svg",
        "images/logo/LOGO_SRn.svg"
    ]

    useEffect(() => {
        const intervalId = setInterval(() => {
            if(imgCount !== 2){
                setImgCount(prevState => prevState + 1)
            } else {setImgCount(0)}
        }, 3000)
        return () => clearInterval(intervalId);
    }, [imgCount])

    return(
        <div className="imgText-container">
            <img src={imgTexts[0]} alt='' className={imgCount === 0 ? "showImg" : null}/>
            <img src={imgTexts[1]} alt='' className={imgCount === 1 ? "showImg" : null}/>
            <img src={imgTexts[2]} alt='' className={imgCount === 2 ? "showImg" : null}/>
        </div>
    )
}
Emil
  • 125
  • 1
  • 2
  • 10

2 Answers2

1

Using setInterval in useEffect is a bit tricky. I suggest you to update your implementation with setTimeout instead. Since you are doing a setState in your react hook, it re-renders your component which cause another call to the useEffect.

useEffect(() => {
  const intervalId = setTimeout(() => {
    if(imgCount !== 2){
      setImgCount(prevState => prevState + 1)
    } else {setImgCount(0)}
  }, 3000)
  return () => clearTimeout(intervalId);
}, [imgCount])
sadrzadehsina
  • 1,331
  • 13
  • 26
1

You setup an interval to fire after 3000 ms only to tear it down when it fires to setup a new interval to fire after 3000 ms to tear it down again and re-setup a fresh interval and so forth. Seems a bit cumbersome. Can't really see how that's causing the error message you posted but why not simplify the code and see if that solves it:

import React, { useState, useEffect } from 'react';

const images = [
    "images/logo/LOGO_SDe.svg", 
    "images/logo/LOGO_SRe.svg",
    "images/logo/LOGO_SRn.svg",
];

const LogoText = () => {
    const [index, setIndex] = useState(0);
    const updateIndex = () => setIndex(i => (i+1)%3);
    
    useEffect(() => {
        const intervalId = setInterval(updateIndex, 3000);
        return () => clearInterval(intervalId);
    }, []);

    return (
        <div className="imgText-container">
            <img src={images[0]} alt='' className={index === 0 ? "showImg" : null}/>
            <img src={images[1]} alt='' className={index === 1 ? "showImg" : null}/>
            <img src={images[2]} alt='' className={index === 2 ? "showImg" : null}/>
        </div>
    );
};
Martin
  • 5,714
  • 2
  • 21
  • 41