skip to Main Content

I need to reload a GIF image (CHECKMARK_ANIMATION_ICON is the source) to start the gif animation every 12 seconds or every time the activeIndex is changing.

This is my code:

   const reloadImgSource = (imgSource) => {
       setTimeout(() => {
       setImgSource("");
       setImgSource(imgSource);
      }, 1);
   };

  const handleActiveDot = (index, item) => {
    setActiveIndex(index);
    setActiveTopBonus(item);
    reloadImgSource(CHECKMARK_ANIMATION_ICON);
  };

  useEffect(() => {
    const activeIndexInterval = setInterval(() => {
      reloadImgSource(CHECKMARK_ANIMATION_ICON);
      if (topBonusList && activeIndex !== topBonusList.length - 1) {
        setActiveIndex(activeIndex + 1);
      } else {
        setActiveIndex(0);
      }
    }, 12000);

    return () => clearInterval(activeIndexInterval);

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeIndex, topBonusList]);
<img src={`${imgSource}`} alt="Checkmark Icon" />

This code is working but I think the solution in reloadImgSource is a workaround.
I used setTimeout set to 1 because otherwise the animation is not triggered as the source is not set to an empty string and then back to the original value to retrigger the GIF.

Is there a better solution I can implement for reloadImgSource that allows me to trigger the load of the GIF when the function is fired?

Note that I cannot use hash in the image source as the gif will not be cached and this is a problem for me

2

Answers


  1. There is a way how you can do that

    function App() {
      const [activeInbox, setActiveInbox] = useState(0);
      const [animation, setAnimation] = useState(false);
    
      useEffect(() => {
        setAnimation(true);
        const timeout = setTimeout(() => {
          setAnimation(false);
        }, 1200);
    
        return () => {
          clearTimeout(timeout);
        };
      }, [activeInbox]);
    
      return (
        <div className="App">
          {animation && (
            <img
              src={`https://cdn.dribbble.com/users/315048/screenshots/3710002/check.gif?${activeInbox}`}
            />
          )}
          <button onClick={() => setActiveInbox((i) => i + 1)}>
            Change active inbox
          </button>
        </div>
      );
    }

    But I’d suggest avoiding such kind of implementations because the gif won’t be cached properly, and the client will load a new gif every inbox update. If you can use another kind of animation, look at SVG.

    Login or Signup to reply.
  2. useState hook doesn’t change state immediately line by line, but it schedule updating state, it is the reason the first setImgSource which tries to empty imgSource will be ignored.

    try:

    const reloadImgSource = (imgSource) => {       
       setImgSource("");
       setTimeout(() => {
           setImgSource(imgSource);
       }, 1);
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search