yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-7] 리코일을 통한 파이어베이스 실시간 데이터 저장 문제 #216

Closed lulla-by closed 1 year ago

lulla-by commented 1 year ago

질문 작성자

이예솔

문제 상황

image

image

프로젝트 저장소 URL

환경 정보

yamoo9 commented 1 year ago

문제 상황

문제 해결

셀렉터 내부에서 onSnapshot을 사용하는 것은 적절하지 않습니다. 다른 방법으로 접근해야 합니다. 참고로 onSnapshot은 이벤트 구독(subscription)이므로 컴포넌트 최초 마운트 이후 1회 연결되어야 하며, 컴포넌트가 언마운트 될 때 해제(unsubscription)되어야 합니다.

아래와 같이 사용하는 것이 일반적입니다. 참고해보세요. 😃

function Component() {

  // 아톰 상태 및 상태 업데이트 함수를 useRecoilState 훅으로 가져오기
  const [questions, setQuestions] = useRecoilState(questionsState);

  useLayoutEffect(() => {
    // 컴포넌트 마운트 시점에 1회 onSnapshot 연결
    const unsubscription = onSnapshot(collection(dbService, "question"), (snapshot) => {
      const newCollections = snapshot.docs.map((item) => item.data());
      // 변경이 감지되면 atom 상태 업데이트
      setQuestions(newCollections);
    });

    // 컴포넌트 언마운트 시점에 연결된 onSnapshot 해제
    return unsubscription; 
  }, []);

  // question 컬렉션 데이터를 Firestore에서 가져오는 이벤트 리스너(함수)
  const handleFetchQuestions = async () => {
    const querySnapShot = await getDocs(collection(dbService, "question"));
    const newQuestions = querySnapShot.docs.map((doc) => ({
      ...doc.data(),
    }));

    // atom 상태 업데이트
    setQuestions(newQuestions);
  }

  return (
    <>
      <button type="button" onClick={handleFetchQuestions}>Question 컬렉션 가져오기</button>
      {/* ... */}
    </>
  );

}

export Component;

아래는 선언된 questionsState 아톰입니다. 아톰 이펙트를 사용해 아톰 상태가 변경되면 Console 패널에 출력합니다.

export const questionsState = atom({
  key: "questionsState",
  default: [],
  // 아톰 이펙트 : 아톰 상태가 변경되면 콜백 되는 함수 연결
  effects: [
    ({onSet}) => {
      // 아톰 상태가 변경되면 새 값을 Console 패널에 출력
      onSet((newValue) => console.log('questionsState 아톰 상태 값: ', newValue));
    },
  ],
});