In this post, we will learn how to crop an image before uploading in React JS. For cropping the image we will use a library called ‘react-easy-crop’ in this tutorial.
Video | React JS Crop Image Before Upload
As you can see in the above demo video when the user selects an image by clicking on Choose Image button. The selected image will be loaded into our image cropper. When the cropping is done we will display the cropped image.
Steps to Crop Image Before Uploading
- Installing react-easy-crop Package
- Creating File Input Component
- Create Image Cropper Component
- Using FileInput and ImageCropper Components
Let’s first create our react app using the create-react-app command.
npx create-react-app crop-image-reactjs
Installing react-easy-crop Package
Now, let’s install the react-easy-crop package using the following command.
npx install react-easy-crop
Creating File Input Component
After installing the library. Let’s create a component to choose an image from our local machine. We will create a file named FileInput.js.
FileInput.js
import React, { useRef } from "react";
function FileInput({ onImageSelected }) {
const inputRef = useRef();
const handleOnChange = (event) => {
if (event.target.files && event.target.files.length > 0) {
const reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
reader.onload = function (e) {
onImageSelected(reader.result);
};
}
};
const onChooseImg = () => {
inputRef.current.click();
};
return (
<div>
<input
type="file"
accept="image/*"
ref={inputRef}
onChange={handleOnChange}
style={{ display: "none" }}
/>
<button className="btn" onClick={onChooseImg}>
Choose Image
</button>
</div>
);
}
export default FileInput;
Inside FileInput Component, we have an input element of type file which will aspect only images. And a button named Choose Image. We are using the useRef hook to handle the input element.
The handleOnChange() function will be invoked whenever the user chooses an image. In this function, we validate the file and store the selected image file path into a state variable.
Create Image Cropper Component
Now let’s create the actual image cropper component. For that create a component with the name ImageCropper.js.
ImageCropper.js
import React, { useState } from "react";
import Cropper from "react-easy-crop";
function ImageCropper({ image, onCropDone, onCropCancel }) {
const [crop, setCrop] = useState({ x: 0, y: 0 });
const [zoom, setZoom] = useState(1);
const [croppedArea, setCroppedArea] = useState(null);
const [aspectRatio, setAspectRatio] = useState(4 / 3);
const onCropComplete = (croppedAreaPercentage, croppedAreaPixels) => {
setCroppedArea(croppedAreaPixels);
};
const onAspectRatioChange = (event) => {
setAspectRatio(event.target.value);
};
return (
<div className="cropper">
<div>
<Cropper
image={image}
aspect={aspectRatio}
crop={crop}
zoom={zoom}
onCropChange={setCrop}
onZoomChange={setZoom}
onCropComplete={onCropComplete}
style={{
containerStyle: {
width: "100%",
height: "80%",
backgroundColor: "#fff",
},
}}
/>
</div>
<div className="action-btns">
<div className="aspect-ratios" onChange={onAspectRatioChange}>
<input type="radio" value={1 / 1} name="ratio" /> 1:1
<input type="radio" value={5 / 4} name="ratio" /> 5:4
<input type="radio" value={4 / 3} name="ratio" /> 4:3
<input type="radio" value={3 / 2} name="ratio" /> 3:2
<input type="radio" value={5 / 3} name="ratio" /> 5:3
<input type="radio" value={16 / 9} name="ratio" /> 16:9
<input type="radio" value={3 / 1} name="ratio" /> 3:1
</div>
<button className="btn btn-outline" onClick={onCropCancel}>
Cancel
</button>
<button
className="btn"
onClick={() => {
onCropDone(croppedArea);
}}
>
Done
</button>
</div>
</div>
);
}
export default ImageCropper;
In ImageCropper component, we have used the <Cropper /> component from react-easy-crop library. We are passing the image, aspect, crop ( x and y coordinated { x: number, y: number }), and zoom as props.
We also have the radio input elements to get the crop aspect ratio and the cancel button to discard the crop and the done button to finish the crop.
The onCropComplete() function will be triggered when the crop is completed and returns croppedAreaPercentage and croppedAreaPixels. We get the croppedAreaPixels and store it in the state variable.
The onAspectRatioChange() function is used to update the aspectRatio state variable when the user switched between different aspect ratios.
Using FileInput and ImageCropper Components
Finally, we will use the created component inside the App.js file. Here is the code for App.js
App.js
import React, { useState } from "react";
import FileInput from "./components/FileInput";
import ImageCropper from "./components/ImageCropper";
function App() {
const [image, setImage] = useState("");
const [currentPage, setCurrentPage] = useState("choose-img");
const [imgAfterCrop, setImgAfterCrop] = useState("");
// Invoked when new image file is selected
const onImageSelected = (selectedImg) => {
setImage(selectedImg);
setCurrentPage("crop-img");
};
// Generating Cropped Image When Done Button Clicked
const onCropDone = (imgCroppedArea) => {
const canvasEle = document.createElement("canvas");
canvasEle.width = imgCroppedArea.width;
canvasEle.height = imgCroppedArea.height;
const context = canvasEle.getContext("2d");
let imageObj1 = new Image();
imageObj1.src = image;
imageObj1.onload = function () {
context.drawImage(
imageObj1,
imgCroppedArea.x,
imgCroppedArea.y,
imgCroppedArea.width,
imgCroppedArea.height,
0,
0,
imgCroppedArea.width,
imgCroppedArea.height
);
const dataURL = canvasEle.toDataURL("image/jpeg");
setImgAfterCrop(dataURL);
setCurrentPage("img-cropped");
};
};
// Handle Cancel Button Click
const onCropCancel = () => {
setCurrentPage("choose-img");
setImage("");
};
return (
<div className="container">
{currentPage === "choose-img" ? (
<FileInput setImage={setImage} onImageSelected={onImageSelected} />
) : currentPage === "crop-img" ? (
<ImageCropper
image={image}
onCropDone={onCropDone}
onCropCancel={onCropCancel}
/>
) : (
<div>
<div>
<img src={imgAfterCrop} className="cropped-img" />
</div>
<button
onClick={() => {
setCurrentPage("crop-img");
}}
className="btn"
>
Crop
</button>
<button
onClick={() => {
setCurrentPage("choose-img");
setImage("");
}}
className="btn"
>
New Image
</button>
</div>
)}
</div>
);
}
export default App;
In the above code, we have defined a few useState variables like ‘image’ to store the user-selected image, ‘currentPage’ to show and hide components based on its value, and ‘imgAfterCrop’ to store the cropped image.
And we have written three functions onImageSelected(), onCropDone(), and onCropCancel() inside our App.js component.
The onImageSelected() function is passed to the FileInput component as a prop. This function will be invoked when the user selected an image file.
Inside this function, we are updating the image state variable with the value which we get from FileInput Component, and we also update the currentPage state variable.
The onCropDone() and onCropCancel() functions is passed to the ImageCropper Component as a prop. This function will be called when the user clicks on the Done button.
This function will take croppedAreaPixels as a parameter and draws only the cropped image on the canvas. Then we use the toDataURL() method on canvas to get the image and store it in the ‘imgAfterCrop’ state variable.
Also Check out:
- Create Image Magnifier in React JS
- Draw Rectangle on Image in React JS
- Create Image Zoom In and Zoom Out Component in React
The onCropCancel() function, is invoked when the Cancel button is clicked. It will reset the image and currentPage state variables.
Output

Conclusion
In this tutorial, we have learned how to crop images before uploading in React JS. Hope it was helpful. Thanks