I'm currently trying to create a React component to upload and crop an image using Croppie library.
I've found this code sample
import "croppie/croppie.css"
import { Button, Grid } from "@material-ui/core"
import * as React from "react"
import Croppie from "croppie"
export function CroppieExample() {
const [image, setImage] = React.useState("")
const [croppie, setCroppie] = React.useState<Croppie | null>(null)
function handleImage(image: string) {
setImage(image)
const el = document.getElementById("image-helper")
if (el) {
const croppieInstance = new Croppie(el, {
enableExif: true,
viewport: {
height: 250,
width: 250,
},
boundary: {
height: 280,
width: 400,
}
});
croppieInstance.bind({
url: image,
});
setCroppie(croppieInstance)
}
}
function handleSubmit(event: any) {
event.preventDefault()
if (croppie !== null) {
croppie.result({type: 'base64',
size: {
width: 480,
height: 480
}}).then((blob) => {
console.log(blob)
}
)
}
}
return (
<form onSubmit={handleSubmit}>
<Grid container spacing={2}>
{image === "" && (
<Grid item xs={12}>
{/* Your image upload functionality here */}
<ImageUpload image={image} setImage={handleImage} />
</Grid>
)}
{image !== "" && (
<Grid item container justify="center" xs={12}>
<div id="image-helper"></div>
</Grid>
)}
<Grid container item xs={12} justify="flex-end">
<Button color="primary" variant="contained" type="submit">
Submit
</Button>
</Grid>
</Grid>
</form>
)
}
I've a question regarding the conditional part of this piece of code:
In order to work, a Croppie instance must be attached to the div element "image-helper". The handleImage event is in charge of the croppieInstance creation. But by the time it is called, it seems that is not rendered so no croppie instance can be created.
Is my assumption right?
If it's the case, what would be the React way to correct the code?
Thank you for your help
Yes your analysis is right. The code snippet is egregious. The correct way in React to initialize any code when DOM elements are finally available is via a callback ref.
const initImageHelper = useCallback(
(element) => {
if (element) {
const croppieInstance = new Croppie(element, settings);
croppieInstance.bind({ url: image });
setCroppie(croppieInstance);
}
}, [image]
);
{image !== "" && (
<Grid item container justify="center" xs={12}>
<div id="image-helper" ref={initImageHelper}></div>
</Grid>
)}