Jaeger
Jaeger

Reputation: 1754

Why is array.length equal to 0 when it's not empty, and how can I loop through it?

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:

I have the feeling I'm ignoring something obvious.

Thank you in advance

Upvotes: 0

Views: 409

Answers (1)

Belmin Bedak
Belmin Bedak

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

Related Questions