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?
CodePudding user response:
Ok so there is a problem in your function, this is not a good practice to set the state in a for loop, do it this way:
const loadImageHandler = (event) => {
setImageUpload(event.target.files);
setShowProgress(true);
setFileObj(event.target.files.map(item => ({
file: item,
url: URL.createObjectURL(item)
})))
};
CodePudding user response:
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]);
};