How to display spinner or progress bar while image loading?

2k views Asked by At

I am making the react, next.js app on which I am displaying various images: enter image description here

The user is clicking on the item from the list on the left, and it's getting three images on the right. The images are displaied based on next.js Image component:

            <Image
          src={visualizationData[0]}
          quality={50}
          alt="Zdjęcie oryginalne"
          width={600}
          height={600}
        />

Where visualizationData is a variable using the State Hook and returing 3 urls to photos that user wants to display:

const [visualizationData, setVisualizationData] = useState(getVisualizationData(props.history.model.name, props.history.dataLists[0].replace('img/', '')));

So it returns something like this: enter image description here

Everything is working fine, but slow, because backend needs to convert .tif photos to .jpg and it takes like 3 seconds. I want to display for this 3 seconds a spinner or something similar to spinner instead of leaving the user with the old visualizations.

How to make it? I don't know how to check that photo is loaded or not, because I am only passing urls to the src prop of the Image component.

Here is a code of getVisualizationData(modelName, pathAndPhotoName):

    export function getVisualizationData(modelName, pathAndPhotoName) {
  const photoName = pathAndPhotoName.split('/').slice(-1)[0];
  const datasetPath = pathAndPhotoName.replace(`/${photoName}`, '');
  const visualizationData = [
    `${backendUrl}download/datasets/${datasetPath}/image/${photoName}`,
    `${backendUrl}download/datasets/${datasetPath}/mask/${photoName}`,
    `${backendUrl}download/models/${modelName}/Predictions/1/${photoName}`];
  return visualizationData;
}

It is converting the path to the photos and returning it in an array.

1

There are 1 answers

1
fjplaurr On

You can create a isLoading boolean. If isLoading is true, then show the Spinner. If not, then the data has been fetched and you can stop showing the spinner and start showing the pictures.

Please notice I don't have enough information about what getVisualizationData returns exactly. But basically, it should return a Promise resolved with the value fetched. So look at this code, get the idea and apply it.

  const [isLoading, setIsLoading] = useState(false);
 
  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);
 
      const result = await getVisualizationData(props.history.model.name, props.history.dataLists[0].replace('img/', '')); //Please check this line    
      setVisualizationData(result);
      setIsLoading(false);
    };
    fetchData();
  }, []);

Then in your component, you can render a spinner while isLoading is true. When it's false, then you render what you want to show:

return(
{isLoading ? (
        <SpinnerComponent />
      ) : (
        <div>
          //Render here your pictures
        </div>
      )}
)