In a react-native application, I call an action sends data to firebase. but after the call, I get an error whose source seems to be with the way the snapshot listener is working. the add-msg action more or less looks like this:
create data:
const addMsg = (msg, convoIds) => {
console.log('Firestore Write: (actions/conversation) => addMsg()');
return firebase.firestore().collection('messages').add({
time: firebase.firestore.FieldValue.serverTimestamp(),
sender: msg.sender,
receiverToken: msg.receiverToken,
sessionId: msg.sessionId,
read: false,
charged: false,
userConvos: [ convoIds.sender, convoIds.receiver ],
content: {
type: 'msg',
data: msg.text
}
});
};
I also have a snapshot listener (that executes in componentDidMount) that populates a redux store with messages from a collection in firestore. the snapshot listener looks like:
export const getMessages = (convoId) => {
const tmp = convoId == null ? '' : convoId;
return (dispatch) => {
console.log('Firestore Read (Listener): (actions/conversation) => getMessages()');
return new Promise((resolve, reject) => {
firebase
.firestore()
.collection('messages')
.where('userConvos', 'array-contains', tmp)
.orderBy('time')
.onSnapshot((querySnapshot) => {
const messages = [];
querySnapshot.forEach((doc) => {
const msg = doc.data();
msg.docId = doc.id;
msg.time = doc.get('time').toMillis();
messages.push(msg);
});
dispatch({ type: types.LOAD_MSGS, payload: messages });
resolve();
});
});
};
};
the corresponding reducer that populates a flatList in the same screen component which looks like:
const INITIAL_STATE = {
messages: []
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case types.LOAD_MSGS:
return {
messages: action.payload
};
default:
return { ...state };
}
};
Problem: once the data sends, I immediately get an error TypeError: null is not an object (evaluating 'doc.get('time').toMillis'
. if I reload the application, navigate back to the screen in question, the msg appears, and so does the time data. So my guess is something is happening with the delay in the promissory nature of firebase calls, and the delay causes a null initialization of the time value, but its long enough to crash the application.
Question: what is actually happening behind the scenes here and how can I prevent this error?
msg.time = doc.get('time').toMillis();
do an experiment in the form ofconsole.log(doc.get('time').toMillis())
. You will see whether that's the thing which is null or not. This is a key information that you need in order to solve your problem. – Lajos Arpad