So I'm trying to make a component to select multiple images and display a preview, so then the user can see the selected images and decide to upload it or not.
So here's my code to select images and display the preview :
const [fileObj, setFileObj] = useState([]);
const loadImageHandler = (event) => {
setImageUpload(event.target.files);
setShowProgress(true);
for (let i = 0; i < event.target.files.length; i++) {
setFileObj((arr) => [
...arr,
{
file: event.target.files[i],
url: URL.createObjectURL(event.target.files[i]),
},
]);
}
};
return (
<div className={classes.container}>
<div className={classes.imgPreview}>
{fileObj.length > 2 &&
fileObj.map((obj, index) => <img id={index} src={obj.url} />)}
</div>
<div>
<label id="articleImg">Select images for your article :</label>
<input
name="articleImg"
type="file"
onChange={loadImageHandler}
accept="image/*"
required={required}
multiple
/>
</div>
</div>
);
The problem is that when I select my images, the input field indicates that there are 3 images selected for example, but the preview does not display anything. It is when I select the images a second time that the preview shows the new images that have just been selected and the previous ones. How can I update my preview during the first selection?
That because you are using setState method in the loop. So in next render, actually there is only one data in fileObj array. Because of 'fileObj.length > 2' condition, so the image won't be rendered.
Try change 'loadImageHandler' method to this way.
const loadImageHandler = (event) => {
setImageUpload(event.target.files);
setShowProgress(true);
// First to figure out the result array by using map method
const result = event.target.files.map(v => ({
file: v,
url: URL.createObjectURL(v),
}));
setFileObj((arr) => [...arr, ...result]);
};