skip to Main Content

I try to change background-image using setInterval which is compileable, but the problem is, it only change once from image a.jpg to b.jpg.

here is my code ;


  const [currentImage, setCurrentImage] = useState<string>("/a.jpg");
  useEffect(() => {
    const intervalId = setInterval(() => {
      if (currentImage === "/a.jpg") {
        setCurrentImage("/b.jg");
      } else if (currentImage === "/b.jpeg") {
        setCurrentImage("/c.jpg");
      } else {
        setCurrentImage("/a.jpg");
      }
    }, 6000);
    return () => clearInterval(intervalId);
  }, []);

how to correctly wrote setInterval in nextjs and make it return to starting image?

2

Answers


  1. You’re using the currentImage variable in the useEffect callback but since you don’t include it in the dependency array, it will always have its initial value ("/a.jpg") when useEffect invokes it. This is what’s known as a stale reference.

    To fix this you need to add currentImage to the dependency array so that the callback gets updated when it changes.

    useEffect(() => {
      const intervalId = setInterval(() => {
        if (currentImage === "/a.jpg") {
          setCurrentImage("/b.jg");
        } else if (currentImage === "/b.jpeg") {
          setCurrentImage("/c.jpg");
        } else {
          setCurrentImage("/a.jpg");
        }
      }, 6000);
      return () => clearInterval(intervalId);
    }, [ currentImage ]);
    

    Any variable that the useEffect callback uses must always be included in the dependency array

    Note that this means that the "timer" will restart every time currentImage changes. If this is not acceptable, you’ll need a more complex solution involving useRef.

    Login or Signup to reply.
  2. Here is a way to handle your use case. I’m not sure I’m advocating it, but it totally works.

    const colorMap = {
    "/a.jpg":"/b.jpg",
    "/b.jpg":"/c.jpg",
    "/c.jpg":"/a.jpg"
    }
    
    
      const [currentImage, setCurrentImage] = useState<string>("/a.jpg");
      useEffect(() => {
        const intervalId = setInterval(() => {
         setCurrentImage(prevState => colorMap[prevState])
        }, 6000);
        return () => clearInterval(intervalId);
      }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search