React에서 Firestore의 데이터를 onSnapshot으로 가져올 경우 보통 컴포넌트가 마운트 해제될 때에 unsubscribe로 연결을 끊어준다.
보통 아래와 같이 사용된다.
useEffect(() => {
const unsubscribe = firebase.firestore().collection('data')
.orderBy('createAt', 'desc')
.limit(30)
.onSnapshot((result) => {
const resultData = [];
result.forEach((doc) => {
resultData.push(doc.data());
});
setCommentData(resultData);
setIsLoading(false);
});
return () => {
unsubscribe();
};
}, []);
반면에 redux-saga-firebase(rsf)에서는 unsubscribe를 내부적으로 다루고 있으나, redux-saga를 바로 이해하고 있지 않으면, 어떻게 처리해야할지 알 수 없다.
function* getComments(action) {
yield fork(
db.syncCollection,
firestore()
.collection(`channel/${action.channelId}/comments`)
.orderBy('createdAt', 'desc'),
{
successActionCreator: (data) => {
let comments = [];
data.forEach((doc) => {
comments = [doc.data(), ...comments];
});
return { type: actions.GET_COMMENTS_SUCCESS, data: comments };
},
failureActionCreator: (err) => ({
type: actions.GET_COMMENTS_FAILURE,
error: err.message,
}),
}
);
}
만약 위와 같이 syncCollection으로 채팅을 불러올 경우, while(true) 안에서 계속 실행되고 있는 상태이기 때문에 fork를 취소해줘야한다.
import { all, fork, cancel } from 'redux-saga/effects';
function* getComments(action) {
const task = yield fork(
... 생략
);
yield take('LEAVE_CHANNEL');
yield cancel(task);
}
그리고 dispatch 하는 컴포넌트에서 상황에 맞게 unsubscribe 처리를 해주면 된다.
useEffect(() => {
dispatch(syncCannelAction(id));
return () => dispatch(syncChannelDone());
// 참고** return () => dispatch({ type: 'LEAVE_CHANNEL" }); 을 함수로 만든 것
}, []);