cbdeveloper
cbdeveloper

Reputation: 31335

How to render images of unknown dimensions using next/image from Next.js?

This is my use case:

From: https://nextjs.org/docs/api-reference/next/image

To render the images, next/image demands you to define the dimensions, either by setting it directly on the <Image/> element, or by setting it on the parent. This is good, because it prevents any layout shift during the load phase of the images.

But since each image will have its own dimensions, I can use the same dimensions for every one.

This is the result I need.

enter image description here

How can I achieve that?

My current idea:

When I upload the image, I'll also have to save its dimensions. Before I started using next/image, I would simple save the image src. Now I'll have to save something like:

post: {
  images: [
    { 
      src: "https://.../image1.jpeg",
      width: X,                          // SHOULD SAVE WIDTH
      height: Y                          // AND HEIGHT
    }
  ]
}

So I'll be able to render it like this:

const image = post.images[0];

return(
  <Image
    src={image.src}
    width={image.width}
    height={image.height}
  />
);

Is this how it should be done? Is there an easier solution to this?

Upvotes: 1

Views: 2514

Answers (1)

cbdeveloper
cbdeveloper

Reputation: 31335

The approach I've described in the question is exactly what I've ended up doing.

I've created this function to read the image dimensions before the upload:

type ImageDimensions = {
  width: number,
  height: number
}

export const getImageDimensions = (file: File) : Promise<ImageDimensions> => {
  return new Promise((resolve,reject) => {
    try {
      const url = URL.createObjectURL(file);
      const img = new Image;
        img.onload = () => {
        const { width, height } = img;
        URL.revokeObjectURL(img.src);
        if (width && height) 
          resolve({ width, height });
        else 
          reject(new Error("Missing image dimensions"));
      };
      img.src=url;
    }
    catch(err) {
      console.error(err);
      reject(new Error("getImageDimensions error"));
    }
  });
};

So now every image is saved with at least the following properties:

image: {
  src: string,
  width: number,
  height: number
}

And I'm rendering just like that:

<Image
  src={image.src}
  width={image.width}
  height={image.height}
/>

It's working as intended.

Upvotes: 2

Related Questions