2

I'm trying to upload multiple images in React (nextjs) from <input onChange={onChange} type='file' name='file' multiple/> But which way is more proper to do it? Some hours of googling didn't helped me This is my approach(that ofc doesn't work, otherwise i would not have to write it):

I stored images' srcs using useState hook:

const [imgsSrc, setImgsSrc] = useState([])

And this is my "input on change handler":

const onChange = (changeEvent: any) => {
    for (let file of changeEvent.target.files) {
        setTimeout(() => {
            const reader = new FileReader()
            reader.readAsDataURL(file)
            reader.onload = () => { setImgsSrc([...imgsSrc, reader.result]) }
            reader.onerror = () => { console.log(reader.error)}
        }, 1000)
            
    }
}

My input one more time

<input onChange={onChange} type='file' name='file' multiple/>

And my way to trying to show images to user

{ imgsSrc.map((link) => { <img src={link}/> }) }

But it doesn't show me anything, so i have couple of questions that my nerve cells would be happy to get an answer to

  1. why it doesn't work
  2. does "saving images to public folder in root app directory" a good approach to save images
  3. can i store base64 encode URLs remotely and get it every request, decode it and get an image

please...

6
  • Try adding the listeners before calling readAsDataURL Commented Apr 18, 2022 at 14:13
  • @morganney well, i found out that it extracts images' base64 url, but doesn't put it in imgsSrc Commented Apr 18, 2022 at 14:21
  • Why are you using setTimeout? You need to preserve the value of file for each iteration. Check this out stackoverflow.com/questions/5226285/…. I would remove the setTimeout. Commented Apr 18, 2022 at 14:23
  • @morganney somehow without setTimeout it can show me null instead of base64 encode url Commented Apr 18, 2022 at 14:31
  • You might like using 'DropzoneJS': react-dropzone.js.org Commented Apr 18, 2022 at 15:02

2 Answers 2

4

You basically have a couple of mistakes that prevent your code from showing anything:

 function App() {
  const [imgsSrc, setImgsSrc] = useState([]);
  const onChange = (e) => {
    for (const file of e.target.files) {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => {
        setImgsSrc((imgs) => [...imgs, reader.result]);
      };
      reader.onerror = () => {
        console.log(reader.error);
      };
    }
  };
  console.log(imgsSrc, imgsSrc.length);
  return (
    <div>
      <input onChange={onChange} type="file" name="file" multiple />
      {imgsSrc.map((link) => (
        <img src={link} />
      ))}
    </div>
  );
}

Since the file reader is asynchronous, you need to tell React to update the state using the most recent state, or you will have bugs, because setState is asynchronous as well, and the loop commands get batched and override the one another.

The fact that you did not have any image output is due to the fact that you are not returning anything from .map.

You can check the fixed version: https://stackblitz.com/edit/react-pgtpnu?file=src%2FApp.js

You can't save files on server if you are using NextJS and you deploy in a serverless environment, you need to use a cloud service, you could use firestore to save base64 strings, or even better, upload the blobs directly to cloudinary, through multer middleware nextJS serverless functions let you write such a function in a few lines.

Sign up to request clarification or add additional context in comments.

Comments

1

Saving images in the public directory is not a good approach you should try cloud computing applications such as AWS, Google, or Cloudinary. but I would prefer using Cloudinary because you can store approximately 10GB of images in a free account and also it is easy to integrate with react applications. How does it work?

1- save your image in Cloudinary through API request then Cloudinary returns the link of the image in response.

2-store the link of the image inside the database

tutorial => upload image cloudinary and react

2 Comments

I will try ) Thanks
Why is saving images in the public directory not a good approach?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.