Reputation: 6634
I am using Redux+Firestore to grab data and populate my store. I'm using .onSnapshot
to listen to data in a given collection. What I'm not able to do is detach the listener once I am finished.
I've read the Firestore docs and understand that in order to detach the listener you need to store the callback (.onSnapshot
) as a variable, and then call that variable to detach.
The issue I'm facing with this is that I'm using Redux (and attaching/detaching in componentDidMount/componentWillUnmount
respectively).
I've seen a pattern used see here (albeit in Vue) where the callback is stored in a local data variable, so I tried dispatching the callback itself to the Redux store but it doesn't receive it.
Code below:
NOTE: I've tried adding true/false bool's as parameters in getRoomActivity
to call unlisten()
based on the link shared above, at this point - I'm at a loss.
// group.js (redux action file)
export const getRoomActivity = (roomId) => (dispatch) => {
const unlisten = roomCollection
.where('room', '==', roomId)
.onSnapshot((querySnapshot) => {
const roomItems = [];
querySnapshot.forEach((doc) => {
roomItems.push(doc.data());
});
dispatch({ type: GET_ROOM_ACTIVITY, payload: roomItems });
});
};
//Room.js (component)
componentDidMount() {
this.props.getRoomActivity(this.props.roomId);
}
componentWillUnmount() {
this.props.getRoomActivity(this.props.roomId);
}
Upvotes: 2
Views: 736
Reputation: 26276
When you use a thunk with dispatch()
, the value returned by the thunk is passed up the chain.
e.g.
function delayedHello(dispatch) {
setTimeout(() => dispatch({type:'delayed-hello', payload:'hello'}), 1000);
return '1s';
}
let val = dispatch(delayedHello);
console.log(val) // logs '1s'
So we can apply this same trait to the thunk you return from getRoomActivity(someRoom)
so that the onSnapshot
's unsubscribe function is passed back to the caller.
// group.js (redux action file)
export const getRoomActivity = (roomId) => (dispatch) => {
return roomCollection // CHANGED: Returned the unsubscribe function
.where('room', '==', roomId)
.onSnapshot((querySnapshot) => {
const roomItems = [];
querySnapshot.forEach((doc) => {
roomItems.push(doc.data());
});
dispatch({ type: GET_ROOM_ACTIVITY, payload: roomItems });
});
};
//Room.js (component)
componentDidMount() {
this.unsubscribe = dispatch(this.props.getRoomActivity(this.props.roomId));
}
componentWillUnmount() {
this.unsubscribe();
}
Upvotes: 3