我写了一个基本的 React Firebase 应用程序,只是为了确定它是如何工作的 .
我有一个react组件( ViewPosts ),它根据Firebase数据库返回的数据集返回一个react组件列表( Post ) .
我在 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;
Post
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 回答
我引入了一个新属性“uid”,并将该UID映射到组件的Key . 然后,当我更新UID和值时,React将其作为更新选中并重新呈现该组件 .
即使我已经将索引包含在键中,直到我删除该键上方的一个组件将是相同的,这解释了当我从顶部删除组件时重新呈现它的原因 .
基本上,如果有相同类型的多个组件,则必须使用唯一键绑定,除非该键已更改,即使值已更改,React也不会重新呈现组件 .
据我所知,React在后台做了什么,创建一个虚拟DOM并将其与现有DOM进行比较,只重新渲染已更改的组件 . 并且似乎在这样做时它会查找密钥,如果有多个,如果它是相同的,它会跳过整个组件
如果你想知道我是如何使用lodash的
_.uniqueId([prefix=''])
方法创建一个密钥的话谢谢,
克隆您的对象,然后设置状态