Home > database >  Reactjs input multiple files with preview not working on first selection
Reactjs input multiple files with preview not working on first selection

Time:08-28

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]);
 };

  • Related