How can you instantiate a .gif file in a React app?

I have a React app that does 3 things; displays the elements in an array, adds an element on button press and removes an element on button press.

Inside of my image, I am displaying my local .gif file. My .gif file is a single animation .gif, I turned off infinite looping because I want the .gif to spawn in and then remain static.

My error comes when I add a second .gif element to my array. Only the first element displays its animation and the rest display the final slide in the .gif.

I believe that I may be able to solve my issue if I manage to instantiate the element but I am not sure how I would go about doing that.

Here is an excerpt from my code::

function App(){
    const [numbValue, numbUpdate] = useState(0);
    const [starsValue, starsUpdate] = useState(null);
    
    function DisplayGIF(numbToDisp){
      let value=[];
      for(let i=0;i<numbToDisp;i++){
        value.push(<img className="icon" src={process.env.PUBLIC_URL + "/once-star-filled.gif"} alt="animated star"/>)
      }
      starsUpdate(<>{value.map(element=>{return element;})}</>);
    }

    function Add(){
      numbUpdate(numbValue+1);
      DisplayGIF(numbValue+1);
    }

    function Sub(){
      numbUpdate(numbValue-1);
      DisplayGIF(numbValue-1);
    }

    return(<>
      <p onClick={Add}>+</p>
      {starsValue}
      <p onClick={Sub}>-</p>
    </>);
  }

Output:: First add :: displays 1 image that is animated until the end Consecutive adds :: displays x images that display the final frame in the animation

Answer

Both the user “some name” and a few similar questions (Restart a gif animation without reloading the file was my favorite similar question) asked on stack overflow posed interesting answers to my question but they were all inadequate and prone to issue, especially in my case when there are possibly thousands of elements created and in use over the lifespan of the users current website session.

One very fun idea posed in the similar question answers was to use document.getElementById(id) and then to set the element src to “” and then set it back to the previous value. Unfortunately, when I applied this solution to my project, the animations on every single gif across my React app reset. It is still an interesting idea.

Near the bottom of the question was actually a brilliant answer posed in similar ways by 3 users. Also, while those who gave a similar answer of add a query to the end of the src with current Date were laughed out of the forum and unjustly downvoted, it was actually a decent answer. Yet, this still isn’t good enough for me because I can possible have multiple elements created in the same millisecond and there is therefore the possibility of duplicate elements.

It seems that the user “some name” read a similar forum post as he came to the same conclusion after a bit of confusion. But his method of appending an id query to the end of the src using a random number was even more barbaric than using the current Date().getTime() method as I expect to have 10-30 components active at once on a single instance which may each have 0-100+ .gif elements. Add that to 20-100 people using this website on their various machines 1-4 times a day and creating random numbers no longer sounds like a swell idea.

This finally brings us to my final solution, in my master javascript file, I map many of the “App” functions, in this, I pass the id of “Card”+index during the map function. Then, once I am inside of the function that I have shared in this forum I adopted an unrelated method posed by the user “some name” where I create an array and I map it for the index value which is slightly more convenient that using a for loop to do the same thing. And in my src, I add the id query as answered in the linked question above but instead of using dates or random numbers, I use an src similar to props.id+"GIF"+index.

EDIT:8/28/21 :: The user “SomeName” brought up a point that while not always true, should be addressed. Under certain circumstances, when I tested the functionality on my React App this error occurred 60% of the time, a gif is not reset when simply adding index. To correct this, add “time”+new Date().getTime().

This updated correction should now work 100% of the time as it while a human may be able to press a single button multiple times per millisecond, the mouse cannot track from the add button to the subtract button and then back to the add button in under a millisecond.

Here is another pseudo excerpt from my code::

return(
   {new Array(starsNumbValue).fill().map((star, index)=>{
        const additive = ""+props.id+"star"+index+"time"+new Date().getTime();//you may also need to add .ToString() after date().getTime() and you may also need to remove the new declaration.
        return(<img
          className="icon"
          src={process.env.PUBLIC_URL + `/once-star-filled.gif?id=${additive}`}
          alt="animated star"
        />);
      })}
);