React组件不会在firebase child_update事件上重新呈现

时间:2016-11-20 06:47:43

标签: javascript reactjs firebase firebase-realtime-database

我已经编写了一个基本的 React + Firebase 应用程序,只是为了确定它是如何工作的。

我有一个反应组件( ViewPosts ),它根据Firebase数据库返回的数据集返回反应组件列表(发布)。

我在componentDidMount()

附加了Firebase事件 child_removed child_added child_changed

我附加的所有事件都运行良好,但只有 child_changed 事件不会重新呈现页面。但是我添加了一个console.log只是为了检查事件是否被触发了。 (我使用firebase控制台更新/删除值)

我认为它可能是钥匙的问题,所以我甚至添加了一个索引,使其独特但仍然没有运气。我在这里遗漏了什么?为什么代码会给我这种行为。

由于React仅更新了更新的组件,即使我删除了新组件或将新组件添加到列表中,列表也不会更新,但是如果我删除了一个组件并且该组件恰好是更新组件(Post)之上的组件,那么由于React被迫重新渲染该组件下面的列表,我可以看到更新后的值。

请帮我确定发生这种情况的原因

ViewPosts

import React, { Component } from 'react';
import * as firebase from 'firebase';
import Post from './Post';

var listItems = null;
var starCountRef = null;
class ViewPosts extends Component {

  constructor(props) {
   super(props);
   this.state = {renderedList: []};
   this.getDatafromDB = this.getDatafromDB.bind(this);
   starCountRef = firebase.database().ref('posts');
  }

  getDatafromDB() {
    listItems = [];
    starCountRef.once('value', snapshot => {
      var results = snapshot.val();
      var resultsKeys = Object.keys(results);
      listItems = resultsKeys.map((key,i) => <Post key={key.toString() + i} value={results[key].value + i } />);

      this.setState({
        renderedList : listItems
      });
    });
  }
  componentDidMount(){

    // Get the data on a post that has been removed
    starCountRef.on("child_removed", snapshot =>  {
      var deletedPost = snapshot.val();
      console.log("The post valued '" + deletedPost.value + "' has been deleted");
      this.getDatafromDB();
    });

    // Get the data on a post that has been removed
    starCountRef.on("child_added", snapshot =>  {
      var addedPost = snapshot.val();
      console.log("The post value '" + addedPost.value + "' has been added");
      this.getDatafromDB();
    });

    starCountRef.on("child_changed", snapshot =>  {
      var changedPost = snapshot.val();
      console.log("The updated post value is " + changedPost.value);
      this.getDatafromDB();
      console.log("this.state.listItems " + this.state.renderedList);
    });

  }
   render() {
   return(
     <div>
      <ul>
        {this.state.renderedList}
      </ul>
      </div>
   );
 }
}

export default ViewPosts;

发布

import React, { Component } from 'react';

class Post extends Component {

  constructor(props) {
   super(props);
   this.state = {value: props.value};
  }

 render() {
   return(
     <li>{this.state.value}</li>
   );
 }
}

export default Post;

2 个答案:

答案 0 :(得分:0)

我引入了一个新属性“uid”,并将该UID映射到组件的Key。 然后当我更新UID和值时,React选择它作为更新并重新渲染该组件。

即使我已经将索引包含在键中,直到我删除该键上方的一个组件将是相同的,这解释了当我从顶部删除组件时重新呈现它的原因。

基本上,如果有相同类型的多个组件,则必须使用唯一键绑定,除非该键已更改,即使值已更改,React也不会重新呈现组件。

据我所知,React在后台做了什么,创建一个虚拟DOM并将其与现有DOM进行比较,并仅重新渲染已更改的组件。并且似乎在这样做时它会查找关键字,如果有多个,如果它相同,它会跳过整个组件

如果您想知道我是如何创建一个使用lodash的_.uniqueId([prefix=''])方法生成一个密钥的密钥

谢谢,

答案 1 :(得分:0)

克隆您的对象,然后设置状态

const clonelistItems = listItems.slice();
this.setState({
    renderedList :clonelistItems
});