[Study] 개발 공부
[React+Vite/TS] firebase 실시간으로 데이터 업데이트 하기(onSnapshot)
지공A
2024. 5. 31. 14:47
[React+Vite/TS] Firebase 쿼리와 패치
1. 인터페이스 작성사진은 없을 수 있음2. useEffect를 사용하여 fetch 함수(쿼리)를 불러 올 것이다.firebase의 query 함수를 사용query(대상 컬렉션, 쿼리 조건 지정)대상 컬렉션 지정 시 firebase의 collection
jee0.tistory.com
위에서는 onDocs 를 사용하여 데이터를 불러왔지만, 실시간으로 데이터를 화면에 반영시키고 싶다.
이럴 때 firebase의 onSnapshot 함수를 사용한다.
1. 한 번만 가져오는 onDocs와 달리, 쿼리에 리스너를 추가하는 onSnapshot 사용
- 즉, 지정한 쿼리(여기에서는 jweetsQuery 라는 쿼리)에 대한 실시간 구독을 한다는 의미
- 변경이 일어나 스냅샷을 받을 때 마다 map을 사용하여 배열을 만들고, 이 배열로 상태를 업데이트
- 즉, 실시간으로 업데이트를 할 수 있다
2. 이 onSnapshot 함수는 unsubscribe(구독취소) 함수를 반환
- 이 함수를 호출하면, 더 이상 실시간 구독을 하지 않는다. 즉, 실시간 변경 데이터를 전송하지 않는다. (리소스 자원 절감)
3. 따라서, useEffect의 cleanup 함수로 unsubscribe 함수를 지정한다.
- 컴포넌트가 언마운트 될 때, unsubscribe 함수가 호출되고 구독을 취소하게 된다.
export default function Timeline() {
const [jweets, setJweets] = useState<IJweet[]>([]);
useEffect(() => {
// 초기값은 null
let unsubscribe: Unsubscribe | null = null;
const fetchJweets = async () => {
// jweets 컬렉션을 createdAt(생성) 내림차순으로 정렬하는 쿼리
const jweetsQuery = query(
collection(db, "jweets"),
orderBy("createdAt", "desc"),
limit(25)
);
// 이벤트 리스너를 연결해줌, 쿼리에 리스너를 연결해준다
// 무언가가 삭제, 편집 또는 생성되었을 때, 데이터를 추출한다.
// unsubscribe 함수를 반환한다.
// -> 이벤트 리스너를 항상 켜놓고 싶지 않음, e.g. 사용자의 자리비움
// -> 유저가 사용 중이 아닐 때, 리스너를 쓸 필요가 없다. 따라서 fetch 함수를 useEffect 내부에서 사용
unsubscribe = await onSnapshot(jweetsQuery, (snapshot) => {
const jweets = snapshot.docs.map((doc) => {
const { jweet, createdAt, userId, username, photo } = doc.data();
return {
jweet,
createdAt,
userId,
username,
photo,
id: doc.id,
};
});
setJweets(jweets);
});
};
fetchJweets();
return () => {
// unsubscribe가 null이 아니라면 unsubscribe 함수 호출
// useEffect는 언마운트일 때, 값을 반환하면서 cleanup 실행
// e.g. 다른 페이지 이동 -> 사용자가 타임라인 페이지를 볼 때만 이벤트를 사용하고 싶음
// useEffect 훅은 타임라인 컴포넌트가 사용되지 않을 때 구독을 취소할 것임
// 즉, 타임라인 컴포넌트가 마운트될 때 구독되고, 언마운트될 때 구독 취소하는 것이다.
unsubscribe && unsubscribe();
};
}, []);
return (
<Wrapper>
{jweets.map((jweet) => (
<Jweet key={jweet.id} {...jweet}></Jweet>
))}
</Wrapper>
);
}