reactjsnext.jsreact-propsnextjs-image

Next.js Image component props onLoadingComplete not working?


I'm trying to get the naturalWidth and naturalHeight from onLoadingComplete props: https://nextjs.org/docs/api-reference/next/image#onloadingcomplete but its not working? Perhaps I'm doing it wrong?

I have this function:

const handleImageLoad = (e) => {
  console.log("load", e);
};

then I have this component from next.js

<Image
  onLoadingComplete={(e) => handleImageLoad(e)}
  className=""
  src={image["data_url"]}
  alt=""
  layout="fill"
  objectFit="contain"
/>

When the image is loaded, it doesn't do anything, if I try to console log, it works, but I don't know why its not working when I'm passing the handleImageLoad

onLoadingComplete={() => handleImageLoad()}

Solution

  • Edit: Fixed in v11.1.3-canary.33


    It appears that the next/image component is not invoking onLoadingComplete handler in case provided src is a data URI. (And I can see you've opened an issue here for the same.)

    For now a workaround can be to use Object URLs. If you wish, you can implement this quite directly. Refer this thread or the linked questions.

    If you want to keep using react-images-uploading, you can use the methods mentioned in this thread and others, to convert the provided data URI to Object URL then pass it as src to next/image. Obviously, this will be more performance heavy operation that handling the uploaded file yourself.

    Here is a working example: https://codesandbox.io/s/jolly-ellis-4htdl?file=/pages/index.js

    Just adding an alternative for the sake of completeness:

    import { useState } from "react";
    import Image from "next/image";
    
    const IndexPage = () => {
      const [src, setSrc] = useState("");
    
      const handleChange = (e) => {
        setSrc(URL.createObjectURL(e.target.files[0]));
        return true;
      };
    
      const handleImageLoad = (e) => {
        console.log("load", e);
      };
    
      return (
        <>
          <input
            type="file"
            id="foo"
            name="foo"
            accept="image/png, image/jpeg"
            onChange={handleChange}
          />
          <div
            style={{
              marginTop: "1rem",
              width: 600,
              height: 600,
              backgroundColor: "blue",
              position: "relative"
            }}
          >
            {src?.length > 0 && (
              <Image
                onLoadingComplete={(e) => {
                  handleImageLoad(e);
                }}
                src={src}
                alt=""
                layout="fill"
                objectFit="contain"
              />
            )}
          </div>
        </>
      );
    };
    
    export default IndexPage;