Your Location is: Home > Javascript

react native foreach Loop is not working perfectly

From: South View: 2670 user14359593 

Question

I am working on a react native application. on a screen, I am getting some images from the memory then read their stats(size, name, type). I have an array to store image objects. But I am getting strange behaviour. Here is my sample code.

const getPhotos =    () =>{
    RNFetchBlob.fs.ls(dirs_read)
    .then((data) =>{
      let i = 0 
      let items = []
      let arrOfImages =  data.filter((elem) => elem.endsWith('jpeg'))
      arrOfImages.forEach((child) =>{
        
        console.log('iteration', ++i)
        RNFetchBlob.fs.stat(`file://${dirs_read}${child}`).then((stats) =>{
        var dateTime = new Date(stats.lastModified);
        var path =stats.path;
          items.push({
            name: child,
            date: ('0' + dateTime.getUTCDate()).slice(-2) + '-' + ('0' + dateTime.getUTCMonth()).slice(-2) + '-' + dateTime.getUTCFullYear(),
            size: formatBytes(stats.size),
            type:'jpeg',
            path: path
          })
          console.log(items,'Items in Loop')
       }).catch((err) => {
         console.log('Some Eror in stats read')
       }) 
      console.log(items,' Items out of Loop')
      })      
    }).catch((error) =>{
     
    })
}

Here I am explaining what I am getting. in the arrofImages i am getting images from memory. I am iterating in this array and for each child, I read their status. to this point everything is fine. I have created and temporary array with name items. in that array in-store image with relevant data with the push method. Here Problem is that the arrOfImages is executing first and after that the items.push is executing. when I console the items array out of the arrOfImages then this is empty. Here I have an out on the console.

I want that when all I get all data then after that I want to show that. if I call the setState function immediately after the item.push then I am getting the data but it is loading slowly. means one by one. I want it smoothly.

Best answer

You can convert your function into an async function. With that keyword await you are telling the async function to wait on that line until RNFetchBlob is ready. When it's ready you can work with that result.

const getPhotos = async () => {
    const data = await RNFetchBlob.fs.ls(dirs_read);
    // The following code will now be executed when RNFetchBlob is ready and data is accessible.
    let i = 0;
    let items = [];
    let arrOfImages = data.filter((elem) => elem.endsWith("jpeg"));
    // and so on ...
  };

Another answer

We need to change two things.

  1. Use async-await instead of Promises;
  2. Use For of loop instead of forEach loop

Please check with below code. i think this will resolve your issue.

    const getPhotos = async () => {
    try {

      let data = await RNFetchBlob.fs.ls(dirs_read);

      let i = 0
      let items = []
      let arrOfImages = data.filter((elem) => elem.endsWith('jpeg'))
      for (const child of arrOfImages) {
        console.log('iteration', ++i)
        try {

          let stats = await RNFetchBlob.fs.stat(`file://${dirs_read}${child}`);
          var dateTime = new Date(stats.lastModified);
          var path = stats.path;
          items.push({
            name: child,
            date: ('0' + dateTime.getUTCDate()).slice(-2) + '-' + ('0' + dateTime.getUTCMonth()).slice(-2) + '-' + dateTime.getUTCFullYear(),
            size: formatBytes(stats.size),
            type: 'jpeg',
            path: path
          })
          console.log(items, 'Items in Loop')
        } catch ((err) => {
          console.log('Some Eror in stats read')
        })
      }
      console.log(items, ' Items out of Loop')

    } catch ((error) => {

    });
  }