Redux Saga Firebase 사용 시 onSnapshot(syncDocument, syncCollection)을 unsubscribe 하는 방법

Yohiz·2021년 4월 26일

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" }); 을 함수로 만든 것
  }, []);
profile
React를 사용하는 웹개발자 입니다.

0개의 댓글