How to manage Compress & Resize Images with Ionic-React using "react-image-file-resizer"

Hello Community,
I am here to ask for help.

I am using an API to get images that have high resolutions & sizes, but when loading the images in the <IonList /> component it took time to load and even the CPU & HDD are used with high percentage when scrolling the list.
So I tried to the use the package react-image-file-resizer to resize dimensions & reduce size of images and the problem is when i want to get result as String to send it back to the <IonImg src={image}/> component, I always get this Promise<void> in the method imageFileResizeCompression below.
This is my code snippet:

File [./utils.ts]:

/** Convert an "Image URL" to a "Blob" type.
 *  Tutorials links:
 *      https://newbedev.com/javascript-image-url-to-blob-javascript-code-example
 *      https://www.tutorialspoint.com/how-to-convert-an-image-to-blob-using-javascript
*/
const convertImageURLToBlob = async (imageInputURL: string) => {
    const blobImage =
      fetch(imageInputURL)
        .then(res => res.blob()) // Gets the response and returns it as a blob
        .then(blob => {
            // Here's where you get access to the blob
            // And you can use it for whatever you want
            // Like calling ref().put(blob)
            return blob;
        });
    return blobImage;
};

const resizeCompressAndReturnNewURL = /* async */ (imageFileBlobInput: Blob) => {
    //let u = '';
    const resizedImage = Compress.imageFileResizer(
    //new Promise((resolve: any) => {
        //Compress.imageFileResizer(    
            imageFileBlobInput, // the file from input of 'Blob' type
            480, // width
            480, // height
            "JPEG", // compress format WEBP, JPEG, PNG
            70, // quality
            0, // rotation
            (uri) => {
                //u = uri.toString();
                //resolve(uri.toString());
                console.log(uri);
                // You upload logic goes here
            },
            "base64" // blob or base64 default base64
    );
   // });    
    return resizedImage;
   //return u;  
};

/** Compress images to downgrade their "Size, Dimension (Width & Height) & Quality"
 *  using "ReactJS Image File Resize" library (react-image-file-resizer).
 *  Tutorials links: 
 *      https://dev.to/wchr/compress-images-in-react-react-image-file-resize-4oni
 *      https://www.npmjs.com/package/react-image-file-resizer
 *      https://pretagteam.com/question/reactjs-resize-image-before-upload 
*/
export const imageFileResizeCompression = async (imageInputURL: string) => {
    const imageFileBlob = await convertImageURLToBlob(imageInputURL); // e.target.files[0];
    console.log('imageFile Size: ', imageFileBlob.size, 'imageFile Type: ', imageFileBlob.type);
    const img =  /* await */ resizeCompressAndReturnNewURL(imageFileBlob); /* .then(x => x); */
    return img;
}

File [./Home.tsx]:

import { imageFileResizeCompression } from '../utils/utils';

<IonList style={{ marginTop: '100px' }}>
<IonThumbnail slot='start'>
    <IonImg src={imageFileResizeCompression(inputURLImageAPI).then(res => res)}/>
</IonThumbnail>  
</IonList>

Thanks in advance.

One potential problem is you’re not awaiting the result of fetch before you return blobImage. Also, you commented out async/await for reiseCompressAndReturnNewUrl, but I’m guessing imageFileSizer() returns a promise, so you’ll need to await that too.

You have to await all your promises.

Hello @ptmkenny,

Thanks for your reply, I also tried the Promise (async/await) but its the same thing.

What do you mean “it’s the same thing?” Your post isn’t really clear about what the problem is, and your code isn’t clear, either.

For example, you have a function resizeCompressAndReturnNewURL, but you don’t actually return a URL in that function. So what is it that you’re trying to do?

@ptmkenny I followed these tutorials in these links
https://dev.to/wchr/compress-images-in-react-react-image-file-resize-4oni & https://www.npmjs.com/package/react-image-file-resizer?activeTab=readme => to use the package react-image-file-resizer, but the problem in the method resizeCompressAndReturnNewURL() is in this part

(uri) => {
       console.log(uri);
       // You upload logic goes here
     }

because the imageFileResizer method return a void in the promise, and I want the URL (String) and at the same time I want to get this new URL of the converted image into the <IonImg src={X} /> component… and in my case in the IonImg component show me a problem that the returned result is a Promise<Void> and it should be an URL (String) without any Promise.

Thanks.

This is really a general React question, or a react-image-file-resizer question, but the problem is that you have commented out async/await here, when you need to use async/await (or return a Promise as described in the README):

const resizeCompressAndReturnNewURL = /* async */ (imageFileBlobInput: Blob) => {
    //let u = '';
    const resizedImage = Compress.imageFileResizer(
    //new Promise((resolve: any) => {
        //Compress.imageFileResizer(    
            imageFileBlobInput, // the file from input of 'Blob' type
            480, // width
            480, // height
            "JPEG", // compress format WEBP, JPEG, PNG
            70, // quality
            0, // rotation
            (uri) => {
                //u = uri.toString();
                //resolve(uri.toString());
                console.log(uri);
                // You upload logic goes here
            },
            "base64" // blob or base64 default base64
    );
   // });    
    return resizedImage;
   //return u;  
};

The package’s README gives this example:

const resizeFile = (file) =>
  new Promise((resolve) => {
    Resizer.imageFileResizer(
      file,
      300,
      300,
      "JPEG",
      100,
      0,
      (uri) => {
        resolve(uri);
      },
      "base64"
    );
  });

You can either return a promise or use async/await, but you have to use one of these two options.

The README Example 1 gives an example of how to

  1. wrap resizer in a function that returns a Promise
  2. call the wrapper function in an async function.

You have to do both of these steps together to get image resizer to return the URL.

Hello @ptmkenny ,
I know that’s a ReactJS question, but in Ionic framework, we can code using Ionic + ReactJS or Ionic + AngularJS
Anyway, I tried what you have said to me, but indeed, it’s the same problem.
I get images from an API, first I should convert those images into a Blob then pass this Blob type file into the Resizer.imageFileResizer component, but always I get Promise<Void> as result, when I use the method resizeCompressAndReturnNewURL() into the other one imageFileResizeCompression ().

Do you have an idea about this topic @ldebeasi ?

Thanks for all.

If you’re getting Promise<void> as a result, then your code is wrong. This is clear from the README documentation for the package: you should be getting the URI if you configure it as described in the example.

This make me crazy haha, I will try again ELSE I will try another package like compressorJS

Thank you anyway for your great help @ptmkenny :smiley: :smiley: :smiley: