当 firebase 更新时,React 组件不会更新

Ale*_*igh 4 javascript firebase reactjs firebase-realtime-database

我为我的智能家居仪表板设置了一个人员跟踪器(内置 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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

Joe*_*afe 5

当您的组件第一次挂载时,它会调用 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})
  });
}
Run Code Online (Sandbox Code Playgroud)