2017-03-09 83 views
4

我为我的智能家居仪表板(内置反应和firebase)设置了人员跟踪器。但是,当firebase数据库更改时,它不会导致反应组件上的重绘。我无法辨别我出错的地方,有人可以帮我吗?当Firebase更新时React组件不会更新

import React from 'react'; 
import * as firebase from 'firebase'; 
import moment from 'moment'; 

export default class IO extends React.Component { 
    constructor() { 
    super(); 
    this.state = { 
     people: [] 
    }; 
    } 

    componentDidMount() { 
    let peopleArray = [] 
    this.dbroot = firebase.database().ref().child('io') 
    this.dbroot.on('value', snapshot => { 
     snapshot.forEach((snap) => { 
     if(snap.val().active === true) { 
      peopleArray.push(snap.val()) 
     } 
     }) 
     this.setState({people: peopleArray}) 
    }); 
    } 

    render() { 
    return(
     <section class="c-module c-module_IO"> 
     <ul> 
      { 
      this.state.people.map((p) => { 
       return <li key={ p.name } class={'status--'+p.status}><img src={p.image} alt={ p.name } /></li> 
      }) 
      } 
     </ul> 
     </section> 
    ) 
    } 
} 

回答

3

当你的组件首先坐骑,它调用ComponentDidMount并初始化peopleArray。这只会执行一次,因此每次从Firebase接收更新时,此阵列都会发生变化。以您目前的执行情况,以peopleArray该基准状态下举行一个指针,而不是价值你是变异的状态。反应没有做深做比较的时候,它检查看看是否有在状态树发生了变化,它的对象比较。这就是为什么你永远不想改变你的状态,总是在设置状态时创建新的对象。这也适用于redux。

超级快速解决方案是将行let peopleArray = []移动到firebase onValue处理程序中,以便每次获取更新时都会创建一个新数组。此外,在当前的实现你要保持你的附加价值火力地堡到同一个阵列,所以你可能会得到重复。我提到的修复方法也会照顾到这一点。

这是你最后的CDM:

componentDidMount() { 
    this.dbroot = firebase.database().ref().child('io') 
    this.dbroot.on('value', snapshot => { 
    let peopleArray = [] 
    snapshot.forEach((snap) => { 
     if(snap.val().active === true) { 
     peopleArray.push(snap.val()) 
     } 
    }) 
    this.setState({people: peopleArray}) 
    }); 
} 
+0

感谢的人!这就像一个魅力! –