react-image-crop icon indicating copy to clipboard operation
react-image-crop copied to clipboard

onImageLoaded not recognized on Next.js

Open DEVELOPLANCE opened this issue 3 years ago • 6 comments
trafficstars

Hi, I didn't manage to use this package on a Next.js setup, I suspect it has to do with the "on image loaded" property since it doesn't return any value for the "imageRef", does anyone manage to use this package on a Next.js project?

DEVELOPLANCE avatar Apr 13 '22 08:04 DEVELOPLANCE

Hi, can you show your code?

dominictobias avatar Apr 13 '22 08:04 dominictobias

import React, { useEffect, useState } from "react"; import ReactCrop from "react-image-crop"; import demoImage from "/public/images/demo.jpg";

function ImageCropper(props) { const { imageToCrop, onImageCropped } = props;

const [cropConfig, setCropConfig] = useState(
    // default crop config
    {
        unit: "%",
        width: 30,
        height: 30,
        aspect: 16 / 9
    }
);

const [imageRef, setImageRef] = useState();

async function cropImage(crop) {
    if (imageRef && crop.width && crop.height) {
        const croppedImage = await getCroppedImage(
            imageRef,
            crop,
            "croppedImage.jpeg" // destination filename
        );

        // calling the props function to expose
        // croppedImage to the parent component
        onImageCropped(croppedImage);
    }
}


function getCroppedImage(sourceImage, cropConfig, fileName) {
    // creating the cropped image from the source image
    const canvas = document.createElement("canvas");
    const scaleX = sourceImage.naturalWidth / sourceImage.width;
    const scaleY = sourceImage.naturalHeight / sourceImage.height;
    canvas.width = cropConfig.width;
    canvas.height = cropConfig.height;
    const ctx = canvas.getContext("2d");

    ctx.drawImage(
        sourceImage,
        cropConfig.x * scaleX,
        cropConfig.y * scaleY,
        cropConfig.width * scaleX,
        cropConfig.height * scaleY,
        0,
        0,
        cropConfig.width,
        cropConfig.height
    );

    return new Promise((resolve, reject) => {
        canvas.toBlob((blob) => {
            // returning an error
            if (!blob) {
                reject(new Error("Canvas is empty"));
                return;
            }

            blob.name = fileName;
            // creating a Object URL representing the Blob object given
            const croppedImageUrl = window.URL.createObjectURL(blob);

            resolve(croppedImageUrl);
        }, "image/jpeg");
    });
}

return (
    <ReactCrop
        src={imageToCrop || demoImage}
        crop={cropConfig}
        ruleOfThirds
        onImageLoaded={(imageRef) => setImageRef(imageRef)}
        onComplete={cropImage(cropConfig)}
        onChange={(cropConfig) => setCropConfig(cropConfig)}
        crossorigin="anonymous" // to avoid CORS-related problems
    />
);

}

ImageCropper.defaultProps = { onImageCropped: () => { } };

export default ImageCropper;

DEVELOPLANCE avatar Apr 13 '22 09:04 DEVELOPLANCE

basically, it doesn't do anything when I load the image from the file input, I figured it's due to the "onImageLoaded" doesn't triggering anything and "imageRef" not passing the first if "(imageRef && crop.width && crop.height)".

When I was manipulating the code by adding: useEffect(() => { if (imageToCrop !== undefined) { setImageRef(imageToCrop) } })

 It worked but I had to create a new image object with 
 const image = new Image()
  image.src = sourceImage

    but it's just return black canvas 

DEVELOPLANCE avatar Apr 13 '22 09:04 DEVELOPLANCE

The normal way to get an image ref is to use useRef not useState but I don't think that would cause issues.

Hard to see what is going wrong without a runnable example actually, but I recommend you integrate v10 of the library not v9, there is an example here - https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o

P.S. Just to be clear the props/code you posted is for version 9 and below, there is no onImageLoaded prop in v10

dominictobias avatar Apr 13 '22 09:04 dominictobias

Just go back to the ver react-image-crop@^8.6.12 or below 10.0.0

@DEVELOPLANCE

x-N0 avatar May 25 '23 02:05 x-N0

@DEVELOPLANCE i have the same problem. I want to have a default cropped image when the users just upload the first image (without need to make any crop). I have version 8.6.9

In my debug, after onImageLoaded, the setImageRef is not working on time. I mean, imageRef is null in the first attemp to crop the image, after upload.

Did you make it work?

bdiazc90 avatar Aug 08 '23 13:08 bdiazc90