react-image-crop
react-image-crop copied to clipboard
onImageLoaded not recognized on Next.js
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?
Hi, can you show your code?
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;
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
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
Just go back to the ver react-image-crop@^8.6.12 or below 10.0.0
@DEVELOPLANCE
@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?