// 기존
useEffect(() => {
onSnapshot() // 방법 1
getDocs() // 방법 2
}, [])
// 문제점
// 모든 컴포넌트에서 각각 한 번씩 항상 데이터를 불러오고 있음.
// onSnapshot() - 실시간 업데이트
// 누군가 글을 쓰면 지금 접속한 모든 유저한테 강제로 onSnapshot()을 쓴 컴포넌트 수만큼 API 콜을 함.
// (읽기 몇만대로 나온 이유)
// 시도 1
function usePosts() {
const docs : any[] = []
function getDocs() {}
useEffect(() => {
getDocs()
}, [])
return docs
}
// 문제점
// 처음 생각한 구조: usePosts()가 항상 존재하고 getDocs()가 한 번만 실행될 것이다.
// 생각 자체가 틀림.
// 1. 생각한 게 맞았으면 유저가 새로고침하기 전까지 글을 쓰든 뭘 하든 실행이 안될 것. (처음 한 번만 로딩되고 그 뒤로 새로 안 가져옴.)
// 2. 생각한 게 틀렸고, usePosts()가 여러 곳에서 실행되어서 useEffect()가 여러 번 실행됨 -> 기존과 똑같음.
// 시도 2
// 리코일 도입
const lastFetchTime: number = Date.now() // recoil atom
function usePosts2() {
const docs : any[] = []
const [fetchTime, setFetchTime] = useRecoilState(lastFetchTime)
function getDocs() {
// 불러오기
setFetchTime(Date.now())
}
useEffect(() => {
if (Date.now() - lastFetchTime < 5) return
getDocs()
}, [])
return docs
}
// 문제점
// 리코일이 너무 느림
// setFetchTime()을 해도 실시간 반영이 안돼서 로직이 작동하지 않음.
// 시도3
// 리액트 쿼리
function usePosts3() {
function getDocs() {
const docs: any[] = []
return docs
}
const { data } = useQuery(
{
queryKey: ["posts"],
queryFn: getDocs,
cacheTime: 5 * 60 * 1000, // 캐시가 저장돼있는 시간 (5분)
staleTime: 10 * 1000 // 캐시의 유효기간 (10초)
// -> 첫번째 fetch 이후 10초가 지나지 않았으면 새로운 요청이 와도 서버로 보내지 않고 로컬 캐시를 리턴함
//
// staleTime이 5분일 경우
// 내가 글을 쓰거나 다른 사람이 글을 쓸 때(posts db에 변경사항이 있을 때) 최대 5분동안 업데이트가 안 될 수 있음
}
)
return data
}
// 컴포넌트
function PostsComponent() {
const posts = usePosts3()
return <></>
}