React Native Async\Await 无法与 setState 一起正常工作

Posted

技术标签:

【中文标题】React Native Async\\Await 无法与 setState 一起正常工作【英文标题】:React Native Async\Await not working properly with setSateReact 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

【问题讨论】:

【参考方案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

以上是关于React Native Async\Await 无法与 setState 一起正常工作的主要内容,如果未能解决你的问题,请参考以下文章

在 React Native 中使用 async/await 处理 API 调用

处理 Async Await 以使用 Firebase 和 react native

React Native Async\Await 无法与 setState 一起正常工作

在 React Native 中,这两种方法中哪种 Async Await 方法更好,为啥?

React-Native:无法将 babel 更新到 ES7

在 async/await 之后使用 .then 是一种好方法吗?