【问题标题】:React native key not updating properly in for-loop?反应本机密钥在for循环中没有正确更新?
【发布时间】:2016-05-02 12:21:40
【问题描述】:

我在我的 React-native 应用程序中有一个函数,我在其中循环遍历数组中的键并从 Firebase 中提取相应的 ref。

但是,在我的 for 循环中,尽管始终评估正确的 ref,但 for 循环本身的键值始终为 3,因此 totalItemsCompleted(等于 @987654322 中键值的长度@) 总是等于 3。

 listenForItems(itemsRef) {
    var userItemsArray = {
        0: [1],
        1: [5, 6],
        2: [8, 9, 10],
        3: [11, 12, 13]
    };

    var pastItems = [];
    var currentItems = [];

    for (var key in userItemsArray) {
        console.log("KEY1 " + key); //key is correct here
        var itemRef = itemsRef.child(key);
        itemRef.on('value', (snap) => {
            var totalItemsOnList = snap.val().items.length;
            var totalItemsCompleted = userItemsArray[key].length;
            console.log("KEY2 " + key); //key is always 3 here
            if (totalItemsOnList===totalItemsCompleted) {
                pastItems.push({
                    title: snap.val().title,
            });
            }
            else {
                currentItems.push({
                    title: snap.val().title,
                });
            }

            this.setState({
                currentItems: this.state.currentItems.cloneWithRows(currentItems),
                pastItems: this.state.pastItems.cloneWithRows(pastItems)
            });
        });
    }
}

【问题讨论】:

  • 欢迎来到异步编程的奇妙世界。您的 for 循环不会等待 firebase 调用完成,因此它会不断更新键值。您可以尝试使用 console.log(snap.name()) 代替密钥吗?
  • @AndréKool 啊哈!这是正确的;我现在正在使用 snap.key() 并获得正确的值(snap.name() 即将被弃用)。非常感谢!
  • 太好了,我会将其添加为答案,以便在遇到此问题时可以帮助其他人。我在名字和密钥之间犹豫不决,我只是拿了我在谷歌搜索上找到的第一个 :)

标签: javascript arrays for-loop firebase react-native


【解决方案1】:

这里的问题是 firebase 的异步特性。您的 for 循环不会等待 firebase 调用完成,因此它会不断更新键值。

除了使用 key 变量,你应该像这样使用你的 firebase 快照的 key:

var itemRef = itemsRef.child(key);
    itemRef.on('value', (snap) => {
        var totalItemsOnList = snap.val().items.length;
        var totalItemsCompleted = userItemsArray[snap.key()].length;
        console.log("KEY2 " + snap.key()); 

【讨论】:

    【解决方案2】:

    下一个代码可以很容易地重现相同的流程:

    for(var i= 0; i< 3; i++) setTimeout(()=> alert(i) ,i * 1000)
    

    虽然您正在创建多个匿名函数实例,但它并未锁定到适当的key 值,而是参考其“按名称”。 因此,任何处理程序调用的变量 key 都包含它在循环期间获得的最后一个值。

    有不同的方法来处理它。 最简单的一种是将处理程序的创建包装到自调用的匿名函数中:

    temRef.on('value', ((keyFixedValue) => {
    return (snap) => {/*all other code*/}
    })(key))
    

    另一种可能的方法是将key 存储为适当HTML 元素的属性值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-24
      • 1970-01-01
      • 2019-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多