Issue
I am trying to create a chat feature in my react native app. I am using react-native-gifted-chat and saving the messages in firestore. Here is the behavior that is occurring:
When I send a message, ALL the messages re render, some of them are duplicates, as you can see I only have 3 messages sent so far, but all these duplicates are making me wonder why the entire thing is re-rendering and why there are duplicates when it does re-render.
The code:
class Chat extends React.Component {
constructor(props) {
super(props)
this.state = {
messages: [],
currentUser: null,
isLoading: true,
messageID: ""
}
}
//---------------------------------------------------------------
async componentDidMount (){
// get user info from firestore
let userUID = Firebase.auth().currentUser.uid
await Firebase.firestore().collection("users").doc(userUID).get()
.then(doc => {
data = doc.data()
this.setState({
currentUser: {
name: data.username,
avatar: data.profilePic,
_id: doc.id,
},
})
})
const messages = []
await Firebase.firestore().collection("chat")
.orderBy("createdAt", "desc")
.limit(50)
.onSnapshot(querySnapshot => {
querySnapshot.forEach((res) => {
const {
user,
text,
createdAt,
} = res.data();
messages.push({
key: res._id,
user,
text,
createdAt,
});
})
this.setState({
messages,
isLoading: false,
});
})
}
//Load 50 more messages when the user scrolls
//
//Add a message to firestore
onSend = async(message) => {
await Firebase.firestore().collection("chat")
.add({
user: {
_id: this.state.currentUser._id,
name: this.state.currentUser.name,
avatar: this.state.currentUser.avatar,
},
})
.then(ref => this.setState({messageID: ref.id}))
await Firebase.firestore().collection("chat")
.doc(this.state.messageID)
.set({
_id: this.state.messageID,
text: message[0].text,
createdAt: message[0].createdAt
}, { merge: true })
}
render() {
if(this.state.isLoading){
return(
<View style = {{backgroundColor: '#000000', flex: 1}}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
return (
<View style={{backgroundColor: '#000000', flex: 1}}>
<GiftedChat
showUserAvatar={true}
renderUsernameOnMessage={true}
messages={this.state.messages}
onSend={message => this.onSend(message)}
scrollToBottom
/>
</View>
)
}
}
Some notes:
- Every time the component mounts, the messages array pushes the messages to the state array.
- The component mounts when I send a message, thus re-rendering the array of messages.
- Each message ID is unique and generated by firebase using "Add".
Let me know how I can fix this issue.
Solution
Duplication is because of just single line
const messages = []
Move this line inside listener, i.e.onSnapShot()
await Firebase.firestore().collection("chat")
.orderBy("createdAt", "desc")
.limit(50)
.onSnapshot(querySnapshot => {
const messages = []
// rest of your code which is having forEach loop
});
The issue was that messages
object was created only once when the component loaded, and you were pushing elements to that object only.
Answered By - Ravi
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.