我为智能家居仪表板设置了人员跟踪器(内置于react和firebase)。但是,当firebase数据库更改时,它不会导致反应组件重绘。我无法告诉我哪里出错了,有人可以帮助我吗?
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>
)
}
}
答案 0 :(得分:4)
当您的组件首次安装时,它会调用ComponentDidMount并初始化peopleArray
。这只执行一次,因此每次从Firebase接收更新时,此阵列都会发生变异。对于当前的实现,您正在改变状态,因为对peopleArray
的引用作为指针保持在状态,而不是按值。 React在检查状态树中是否有变化时,不会进行深度比较,它会进行对象比较。这就是为什么你永远不想改变你的状态,总是在设置状态时创建新对象。这也适用于redux。
超快速解决方法是将行let peopleArray = []
移动到firebase onValue处理程序中,以便每次获得更新时都会创建一个新数组。此外,使用当前实现,您将继续将Firebase值附加到同一个数组上,因此您可能会获得重复项。我提到的修复也会照顾到它。
这是您的最终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})
});
}