Reputation: 21
I've written a basic React + Firebase application just to identify how it works.
I have a react component(ViewPosts) which returns a list of react components(Post) based on the returned data-set from Firebase database.
I've attached the Firebase events child_removed, child_added and child_changed on componentDidMount()
All the events that I'm attaching is working fine but only the child_changed event is not re-rendering the page. but I've added a console.log
just to check if the event is triggered and it is. ( I'm updating/removing the values using the firebase console)
I thought it might be an issue with the keys so i even added an index to make it unique but still no luck.Am I missing something here ? Why is the code giving me this behavior.
Since React update only the updated components, list will not update even if I removed or added a new component to the list, but if i removed one component and that component happens to be a one above the updated component(Post) then since React is forced to re-render the list below that component I can see the updated value.
Please help me to identify why this is happening
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;
Upvotes: 2
Views: 1829
Reputation: 11
Clone your object and then set the state
const clonelistItems = listItems.slice();
this.setState({
renderedList :clonelistItems
});
Upvotes: 1
Reputation: 21
I Introduced a new property "uid" and mapped that UID to the Key of the component. Then when i update the both the UID and the value , React picked it up as a update and re-rendered that component.
Even though that I've included the index to the key until i remove one component above that key will be the same and that explains the reason why it's re-rendered when i removed a component from top.
Basically if there's multiple component of the same type those has to be tied with a unique key and unless that key changed React will not re-render the component even though the value is changed.
As far as i know what React do is in background create a virtual DOM and compares it with the existing one and only re-render the changed components. and seems like when doing so it looks for the key if there's multiple and if its the same it skips the whole component
Also In case if you wonder how i created a key i generated one using lodash's _.uniqueId([prefix=''])
method
Thanks,
Upvotes: 0