Im trying to get this code for image browsing then cropping the browsed image working:
This is the supposed code to be working:
import "./styles.css";
import React, { useState } from "react";
import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css'
export default function App() {
const [src, selectFile] = useState(null);
const onImageChange = (event) => {
selectFile(URL.createObjectURL(event.target.files[0]));
};
const [image, setImage] = useState(null);
const [crop, setCrop] = useState({ aspect: 16 / 9 });
const [result, setResult] = useState(null);
function getCroppedImg(){
const canvas = document.createElement('canvas');
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext('2d');
ctx.drawImage
(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height,
);
const base64Image = canvas.toDataURL('image/jpeg');
setResult(base64Image)
}
return (
<div className="container">
<div className='row'>
<div className='col-6'>
<input type="file" accept ='image/*' onChange={onImageChange}/>
</div>
{src && <div className='col-6'>
<ReactCrop src={src} onImageLoaded={setImage} crop={crop} onChange={setCrop} />
<button className='btn btn-danger' onClick={getCroppedImg} > Crop Image </button>
</div>}
{result && <div className='col-6'> <img src={result} alt='Cropped Image' className='img-fluid' />
</div>}
</div>
</div>
);
}
You can use this sandbox link to immediately test and debug the code and see the error, code testing in sandbox
This full code is not mainly mine, I have been following this tutorial on youtube as im trying to get it working to learn and use it on my main project, But i cannot get it working as in there this error, which is not actually in the tutorial as im not even missing any line of code so i cannot understand why this error happening, appreicated to make me understand why it happened. this is the yt link: yt tutorial code
Also to add, When i try to browse the image in the current code it doesn't work so I actually tried to fix it by adding this line
<img src={src} />
under the it actually started to work for showing the image, but the cropping functionality is not working.
CodePudding user response:
The error you're seeing may be related to how the code is using React's useState
hook.
In React, a hook is a special function that lets you "hook into" React features from your functional components. The useState
hook is a way to add state to a functional component. It takes an initial value for the state and returns an array with two items: the current state value and a function to update the state.
In the code you posted, useState
is being used to create two state variables: src and image
. Here's how the code sets up the initial values for these state variables:
const [src, selectFile] = useState(null);
const [image, setImage] = useState(null);
The first useState
call sets up src
with an initial value of null
, and the second useState
call sets up image
with an initial value of null
.
The error you're seeing may be related to how these state variables are being used in the code. For example, the code is trying to set the src
state variable when the user selects a file:
const onImageChange = (event) => {
selectFile(URL.createObjectURL(event.target.files[0]));
};
Here, the onImageChange
function is being passed to the onChange
attribute of an <input type="file">
element. When the user selects a file, the onImageChange
function is called, which updates the src
state variable using the selectFile
function that was returned by the useState
call.
It's possible that the error you're seeing is related to how the src
state variable is being used in the code. For example, the code is using the src
state variable to set the src
attribute of an <img>
element:
{src && <img src={src} />}
This code uses the "short-circuit" operator (&&
) to only render the <img>
element if src
is truthy (i.e. not null
or undefined
). If src
is null
or undefined
, the <img>
element will not be rendered.
If the error you're seeing is related to the src
state variable, it may be because the src
state variable is not being properly initialized, or because the src
state variable is being set to null
or undefined
at some point in the code.
I would recommend carefully reviewing the code and making sure that the src
state variable is being initialized with a non-null value, and that it is not being set to null
or undefined
at any point in the code. You may also want to check the React documentation for more information on using the useState
hook.
CodePudding user response:
The error you are seeing is because image is null
when you try to access its properties in the getCroppedImg
function. This happens because the image state is not set until the onImageLoaded
prop of the ReactCrop
component is called, which only happens when the image is loaded. However, the getCroppedImg
function is called before the image is loaded, so image is still null
at that point.
One way to fix this would be to check if image is null before trying to access its properties in the getCroppedImg function. You can do this by adding a conditional statement like this:
function getCroppedImg(){
if (image) {
// rest of the code
}
}
Alternatively, you can delay calling the getCroppedImg function until after the image is loaded. To do this, you can pass a callback function to the onImageLoaded
prop of the ReactCrop component, and call the getCroppedImg function from inside that callback. This way, the getCroppedImg function will be called after the image state has been set, so it will not be null at that point.
Here's an example of how you can do this:
function App() {
const [src, selectFile] = useState(null);
const onImageChange = (event) => {
selectFile(URL.createObjectURL(event.target.files[0]));
};
const [image, setImage] = useState(null);
const [crop, setCrop] = useState({ aspect: 16 / 9 });
const [result, setResult] = useState(null);
function getCroppedImg(){
const canvas = document.createElement('canvas');
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext('2d');
ctx.drawImage
(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height,
);
const base64Image = canvas.toDataURL('image/jpeg');
setResult(base64Image)
}
return (
<div className="container">
<div className='row'>
<div className='col-6'>
<input type="file" accept ='image/*' onChange={onImageChange}/>
</div>
{src && <div className='col-6'>
<ReactCrop
src={src}
onImageLoaded={setImage}
crop={crop}
onChange={setCrop}
onImageLoaded={() => getCroppedImg()}
/>
<button className='btn btn-danger' onClick={getCroppedImg} > Crop Image </button>
</div>}