I want to create an image
uplaoder based on base64
and I want to get results as an array
but I got empty!
array, I know maybe it's a asynchronous
issue, but I don't know how to use async, await
in map
any idea?
const [array, setArray] = useState([]);
const fileBase64 = (img) => {
let result = [...img];
setUrlImage(img);
result && result.map(function (img){
let fileReader = new FileReader();
fileReader.readAsDataURL(img);
fileReader.onloadend = async () => {
let res = await fileReader.result;
setArray([...array, res])
};
})
console.log(array)
}
const handleImage = (e) => {
let image = [...e.target.files];
fileBase64(image);
}
<input type="file" multiple={true} onChange={handleImage}/>
Due to this asynchronous
nature, state is being set i.e. push
before data urls
are set in array.
And that's the reason your your array
return empty.
To fix it, you can use create Promise
which gets resolved after load event of each file. And use Promise.all
which would be resolved after each Promise has resolved and then use setArray
:
fileBase64 = (img) => {
return new Promise((resolve, reject) => {
let fileReader = new FileReader();
fileReader.onerror = reject
fileReader.onload = function () {
resolve(fileReader.result)
}
fileReader.readAsDataURL(img)
})
}
handleImage = (e) => {
let image = e.target.files;
Promise.all(Array.from(image).map(this.readAsDataURL))
.then((urls) => {
setArray(urls)
})
.catch((error) => {
console.error(error)
})
}