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
- why it doesn't work
- does "saving images to
public
folder in root app directory" a good approach to save images - can i store base64 encode URLs remotely and get it every request, decode it and get an image
please...
CodePudding user response:
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/App.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.
CodePudding user response:
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