javascriptreactjsbrowser-cachepreloadflicker

React.js Images are flickering on Slow 3G even though the images are preloaded and cached in a Ref variable


My code is shared on my codesandbox and cleaned up into one file.

https://codesandbox.io/s/stackoverflow1-miwjv4?file=/src/App.js

I preloaded the necessary images by those two functions.

export const preloadImage = (src) => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.src = src;
    // img.onload = resolve(img);
    img.onload = () => {
      resolve(img);
    };
    // img.onerror = img.onabort = reject(src);
    img.onerror = img.onabort = () => {
      reject(src);
    };
  });
};

export const preloadAllImages = async (srcArr) => {
  const promises = srcArr.map((src) => {
    return preloadImage(src);
  });

  return await Promise.all(promises);
};

and use them as below

    const srcArr = items.map((item) => item.src);
    console.log(srcArr);
    preloadAllImages(srcArr).then((images) => {
      // console.log(images);
      // console.log(images[0].naturalHeight);

      slidesRef.current = images.map((image, idx) => {
        return (
          <img
            key={Math.random().toString()}
            src={image.src}
            // Elements with ARIA roles must use a valid, non-abstract ARIA role.
            role={`${items[idx].role || "presentation"}`}
            alt={`${items[idx].alt || ""}`}
          />
        );
      });
      console.log(slidesRef.current);
      setIsLoading(false);
    });

If you test the buttons on carousel of my codesandbox with the dev tools on slow 3G, you still can see white screens between the pictures swapped, and also there are unnecessary HTTP requests to the server made. I've been struggling with this for almost 10 hours now. But didn't work out well still. Please help. I don't know why these are happening and how to remove the flickering using 3 pictures preloaded at the same time at the initial loading time. enter image description here


Solution

  • Found one problem in my code and found another issue that might have caused this problem. One problem was that there was a key prop in the img JSX element which was stored in slidesRef ref variable even though it was not being used in some loop or Array.map in the DOM and that might have casued the React diff algorithm to consider those JSX img elements have been changed. So I removed the key prop which was added by mistake when I was testing those elements in the Array.map method.

    With the first problem fixed, the problem still existed; the flickering caused by the unnecessary HTTP requests to the server. The possible issue that might have caused this, I think, in my assumption is that, if the img element gets mounted and unmounted repeatedly, then the browser, after some seconds later, finds the images that are used in those JSX img elments not exist in the browser cache, and seems like it sends a request to the server again for those images.

    I fixed the above problem by using blob for the images that are being used in the JSX elements which get mounted and unmounted repeatedly and this perfectly solved my issue.