Reputation: 1754
I'm bit in confusion, this should be pretty obvious but I'm getting lost trying to figure everything out.
I'm creating a form with React, and the user can select a few images. My initial goal is to display the preview, but for a reason I can't understand, I can't map the array of results even though I can see with a console.log()
that it's not empty
Here is how I create the array:
constructor(props) {
super(props);
this.state = {
// Some other elements
m_filename: [],
};
}
handleMultiUpload() {
let files = document.getElementById('multiple_files_upload');
let files_result = [];
for(let i = 0; i < files.files.length; i++) {
let reader = new FileReader();
reader.readAsDataURL(files.files[i]);
reader.onloadend = function() {
// console.log(reader.result);
files_result.push({
"id": i,
"name": files.files[i].name,
"img": reader.result
});
}
}
this.setState({
m_file: files_result,
});
}
render() {
const { m_file } = this.state;
// rest of my code
}
From there, when I console.log
the m_file
variable, it returns something looking like this:
[
0:
id: 0
name: "file.jpg"
img: "[base64 file rendered here]"
1:
id: 1
name: "cat.jpg"
img: "[base64 file rendered here]"
...etc
]
I'm trying to loop through m_file
by doing the following:
{
m_file !== null && m_file.map(function(tile) {
return (
<li key={tile.id}>
<img src={tile.img}/>
</li>
)
}
The problems are multiples:
m_file.length
returns 0console.log(typeof m_file)
, it returns object. I guess because it's a state
object, but... how can I deal with it, while I have no problem mapping through json elsewhere?I have the feeling I'm ignoring something obvious.
Thank you in advance
Upvotes: 0
Views: 409
Reputation: 9201
From MDN:
The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read.
Since dealing with FileReader
is asynchronous, when you setState
, your variable file_result
is still empty array.
One of possible solution, is call setState
inside reader.onloadend
function, just after pushing items to the array
let self = this;
reader.onloadend = function() {
// console.log(reader.result);
files_result.push({
"id": i,
"name": files.files[i].name,
"img": reader.result
});
self.setState({
m_file: files_result,
});
}
Note: this
keyword would be binded to FileReader
Object, so correct reference shall be kept in variable.
Here is the nice explanation of Async stuff in Javascript - https://stackoverflow.com/a/4560233/3918577
Upvotes: 1