简体   繁体   English

需要帮助弄清楚如何从 firestore 中的异步 function 获取的列表的值更新 state

[英]Need help figuring out how to update state from the values of a list gotten by an async function in firestore

I currently have code that when entering a screen with useFocusEffect, fetches an array of payments, and for each payment within that list there is another async function which is called that retrieves data about that payment including the value of it.我目前有代码,当使用 useFocusEffect 进入屏幕时,获取一组付款,并且对于该列表中的每笔付款,还有另一个异步 function 调用它来检索有关该付款的数据,包括它的价值。 I am trying to sum up the values of the payments in this list and set a state variable too it, but according to my understanding they are all happening at the same time and the state value is updated to just the value of the last payment that is read from the array.我试图总结此列表中的付款值并设置一个 state 变量,但根据我的理解,它们都是同时发生的,并且 state 值更新为最后一次付款的值从数组中读取。 What would be the best way to make it so that my state updates to the sum of the values of the payments?使我的 state 更新为付款总和的最佳方法是什么? I've tried various combinations of solutions with storing values in local variables and setting the state to the local variable in the end but nothing seems to work.我尝试了各种解决方案组合,将值存储在局部变量中,最后将 state 设置为局部变量,但似乎没有任何效果。 Below is the code to help visualize what I am doing.下面是帮助可视化我在做什么的代码。

fetchPaymentsInChat(props.threadID).then((payments) => {
            payments.forEach(pid => {
                  fetchPayment(pid).then(payment => {
                    setAmountReceive(payment.value + amountReceive);
                    console.log(amountReceive, payment.value);
                    if (payment.sender == username) {
                        setAmountReceive(amountReceive + payment.value);           
                    }
                })
            }); 
        });

Any advice would be appreciated!任何意见,将不胜感激!

Ultimately, it comes down to improper Promise chaining and a misunderstanding of how setState callbacks work.最终,它归结为不正确的 Promise 链接和对setState回调如何工作的误解。

fetchPaymentsInChat(props.threadID)
  .then((payments) => {
    payments.forEach(pid => {
      fetchPayment(pid) // <- floating Promises in loop
        .then(payment => {
          setAmountReceive(payment.value + amountReceive);  // <- sums early?
          console.log(amountReceive, payment.value); // improperly attempts to use new amountReceive value
          if (payment.sender == username) {
            setAmountReceive(amountReceive + payment.value); // <- attempts to sum again?
          }
        })
    }); 
});

When using a setState callback from a useState call, it will set the value for the next render of your component - it doesn't update the value for the current render.当使用来自useState调用的setState回调时,它将为组件的下一次渲染设置值——它不会更新当前渲染的值。 There are resources online that explain how useState works, but for the purpose of showing how it's not updated immediately, we can look at this pseudo-code:网上有资源解释useState是如何工作的,但为了展示它是如何不立即更新的,我们可以看一下这段伪代码:

const useState = (initValue) => {
  useState._value = "_value" in useState ? useState._value : initValue;
  return [useState._value, (v) => useState._value = v]
}

let [value, setValue] = useState(0);
console.log(value); // => 0
setValue(1);
console.log(value); // => 0  [but _value is now 1]
setValue(value + 1);
console.log(value); // => 0  [but _value is still 1 (0 + 1)]
// --- start next loop --- (imagine we've gone back to useState(0) line)
[value, setValue] = useState(0);
console.log(value); // => 1
setValue(1);
console.log(value); // => 1  [but _value is still 1]
setValue(value + 1);
console.log(value); // => 1  [but _value is now 2 (1 + 1)]
// --- start next loop --- (imagine we've gone back to useState(0) line again)
[value, setValue] = useState(0);
console.log(value); // => 2
setValue(1);
console.log(value); // => 2  [but _value is now back to 1]
setValue(value + 1);
console.log(value); // => 2  [but _value is now 3 (2 + 1)]
// ...

As can be seen from the above lines, summing against the current value doesn't work as expected.从上面几行可以看出,对当前值求和没有按预期工作。 While a setState callback can be fed a function another callback to update the value that looks like (oldValue) => newValue , we don't need to use it here.虽然可以向setState回调提供 function 另一个回调来更新看起来像(oldValue) => newValue的值,但我们不需要在这里使用它。

This is because both issues can be solved by fixing up the Promise chains using Promise.all combined with Array#map and Array#reduce .这是因为这两个问题都可以通过使用Promise.all结合Array#mapArray#reduce修复 Promise 链来解决。

fetchPaymentsInChat(props.threadID)
  .then((paymentIDs) => {
    return Promise.all(
      paymentIDs.map(pid => {
        return fetchPayment(pid)
          .then(paymentDetails => paymentDetails.value)
      })
    );
  })
  .then((paymentValues) => {
    const paymentSum = paymentValues.reduce((acc, val) => acc + val, 0);
    setAmountReceive(paymentSum);
  })
  .catch(err => {
    /* don't forget error handling */
  })

If the intention is to only sum the payments where the sender is username , instead use:如果打算仅对发件人为username的付款求和,请改用:

fetchPaymentsInChat(props.threadID)
  .then((paymentIDs) => {
    return Promise.all(
      paymentIDs.map(pid => {
        return fetchPayment(pid)
          .then(paymentDetails => {
            return paymentDetails.sender === username ? paymentDetails.value : 0
          })
      })
    );
  })
  .then((paymentValues) => {
    const paymentSum = paymentValues.reduce((acc, val) => acc + val, 0);
    setAmountReceive(paymentSum);
  })
  .catch(err => {
    /* don't forget error handling */
  })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何列出 Flutter Firestore 中文档的值? - How to list values ​from documents in Flutter Firestore? 如何使用帮助文档 ID 更新 Cloud firestore 文档字段? - How can i Update Cloud firestore document Field with the help DocumentID? 如何使用项目列表更新 firestore 文档中的地图 - How to update maps in a document in firestore with a list of items 如何在项目构建器中显示来自 Firestore 的列表 - How to Display list from Firestore in an item builder 如何在 node.js 中为 firestore 构建递归异步/等待 function - How to structure a recursive async/await function for firestore in node.js 如何从 firestore 获取数据并在 textinput 的下拉列表中列出,以便在 react native 中选择 - How to fetch the data from firestore and list out it in dropdown in textinput for picking in react native 如何在时间间隔内管理 Firestore 数据库中文档的离线更新 state - How to manage Offline Update state of document in Firestore database withing time interval 如何从 Firestore 获取特定数据并在 Objective-C 中更新它 - How to fetch specific data from Firestore and update it in Objective-C Firebase Firestore,如何有效地更新对象数组中的多个集合 - Firebase Firestore, How to update multiple collection from array of objects efficiently Flutter Firestore 如何将数组从 firestore 加载到列表 - Flutter Firestore How to load array from firestore to a list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM