【问题标题】:{React Native} Async\Await not working properly with setSate{React Native} Async\Await 无法与 setState 一起正常工作
【发布时间】:2020-08-21 03:03:24
【问题描述】:

有人可以帮助我了解我做错了什么吗? 考虑这个简单的代码

 var images = []; 
 const [funImage, setFunImage] = useState([]);


//Some function that does this below
firebase.firestore().collection('PostedFunActivities').where("location", "==" , place).get().then((querySnapshot) =>{
        querySnapshot.forEach(async(doc) =>{ 
            const ref = firebase.storage().ref('images/'+ doc.data().image)
            const result = await ref.getDownloadURL();
            images.push(result);                                                                   
           })
           setFunImage(images);
       });

我不明白为什么setFunImage(images);images.push(result); 完成将所有结果推送到数组之前执行。我认为 await 会阻止它下面的其余代码 基本上,我要做的事情背后的概念是将我的所有结果推送到images,然后调用setFunImage(images);

我怎样才能做到这一点?有可能吗?

编辑

我更改了我的代码,希望找到一个解决方案,这就是我到目前为止的地方:

firebase.firestore().collection('PostedFunActivities').where("location", "==" , place).get().then((querySnapshot) => {
   querySnapshot.forEach(async(doc) => {
     const ref = firebase.storage().ref('images/' + doc.data().image)
     const result = await ref.getDownloadURL();
     images.push(result);
     setFunImage(...funImage,images);
     }) 
});

有趣的是,当这个函数执行时,funImage 填充了 1 个图像,但是当我刷新它时,它会填充我在我的 firebase 中的其余图像。

看看这个GIF of my running app and the issue with the setState

【问题讨论】:

    标签: reactjs firebase react-native google-cloud-firestore async-await


    【解决方案1】:

    代码不起作用,因为您的 forEach 正在运行异步代码。这意味着它会在您设置图像后完成运行。 这是一个修复,在 cmets 中有一些解释 -

    // No need for images array outside
    const [funImage, setFunImage] = useState([]);
    
    ...
    
    firebase.firestore().collection('PostedFunActivities').where("location", "==" , place).get().then(async (querySnapshot) =>{
        // instead of foreach, using map to aggregate the created promises into one array
        // Promise.all takes an array of promises and resolves after all of them completed running
        // returns an array with the promise results
        const images = await Promise.all(querySnapshot.map(async(doc) =>{ 
            const ref = firebase.storage().ref('images/'+ doc.data().image)
            const result = await ref.getDownloadURL();
            return result;                                         
        }));
        setFunImage(images);
    });
    

    【讨论】:

    • 谢谢老兄,我会尽快测试并告诉你。
    • 不幸的是它不起作用。我没有填充我的 funImage,还有其他想法吗?
    • 您应该尝试将querySnapshot.map 更改为querySnapshot.docs.map,因为querySnapshot 不是您所期望的数组:googleapis.dev/nodejs/firestore/latest/QuerySnapshot.html