firebase에서 문서를 가져오는 방법은 다음과 같다.
const Home = () => {
const [doc, setDoc] = useState([]);
let q = query(
collection(dbService, "문서이름"), //여기서 dbService는 getFirestore()입니다.
orderBy("createdAt", "desc") //생성날짜 내림차순(최신순)으로 가져오기
);
onSnapshot(q, (snapshot) => {
const arr = snapshot.docs.map((doc) => ({...doc.data()}));
setDoc(arr);
});
}
우리는 여기에 무한스크롤을 추가해야한다.
npm install react-bottom-scroll-listener
yarn add react-bottom-scroll-listener
자세한 사용방법은 [npm문서]를 참조.
스크롤 위치나 기타등등 조절할 수 있는듯 하다.
우선 컴포넌트 함수 바깥에 변수 하나를 선언해준다.
let lastVisible = undefined;
const Home = () => {}
lastVisible은 남은 게시글이 있는지 여부를 판단하는 boolean값이 될거다.
모든 게시글을 불러왔을 때 -1로 선언할 예정이다.
let q; //경우에 따라 다르게 선언해야되므로 일단 undefinded 선언
if (lastVisible === -1) {
return //남은 게시글이 없으면 더이상 실행 안함
} else if (lastVisible) {
q = query(collection(dbService, "문서이름"),orderBy("createdAt", "desc"),limit(2),startAfter(lastVisible));
//limit로 몇개를 불러올건지 결정함
//남은 게시글이 있으면 startAfter로 방금전에 불러온 게시글의 다음 글부터 불러옴
} else {
q = query(collection(dbService, "문서이름"),orderBy("createdAt", "desc"),limit(5));
//최초 페이지 렌더링
}
그리고 데이터를 뿌릴 때 lastVisible을 핸들링 해준다.
Array 병합시 꼭 새로 불러온 문서는 뒤에 넣어줘야한다.
안그러면 스크롤을 내리고 있는데 새 글이 맨위에 렌더링되는 참사가....
Array.push 또는 아래와 같이 작성해준다.
onSnapshot(q, (snapshot) => {
const docArr = snapshot.docs.map((doc) => ({...doc.data()}));
const arr = [...doc, ...docArr]; //불러온 데이터와 기존의 데이터를 하나의 Array로 만들자
setDoc(arr);
if(snapshot.docs.length === 0) { //남은 게시글이 없으면
lastVisible = -1;
} else {
lastVisible = snapshot.docs[snapshot.docs.length - 1] //index번호로 받아야 하니 length에서 -1을 해준다
}
});
그리고 최초에 설치한 react-bottom-scroll-listener를 사용해서 스크롤바가 바닥에 닿으면 문서를 불러오는 함수를 실행시켜주자!
hooks의 이름은 다음과 같다.
useBottomScrollListener(콜백함수);
분명 잘 돌아갔던거 같은데
갑자기 선언한 lastVisible이 초기화되지 않는 오류가 발생했다.
컴포넌트를 렌더링 했을 때 lastVisible을 다시 undefined로 선언해주자.
useEffect(() => {
lastVisible = undefined;
},[])
const Home = () => {
const [doc, setDoc] = useState([]);
const getNextPage = () => {
let q;
if (lastVisible === -1) {
return;
} else if (lastVisible) {
q = query(collection(dbService, "문서이름"),orderBy("createdAt", "desc"),limit(2),startAfter(lastVisible));
} else {
q = query(collection(dbService, "문서이름"),orderBy("createdAt", "desc"),limit(5));
}
onSnapshot(q, (snapshot) => {
const docArr = snapshot.docs.map((doc) => ({...doc.data()}));
const arr = [...doc, ...docArr];
setDoc(arr);
if(snapshot.docs.length === 0) {
lastVisible = -1;
} else {
lastVisible = snapshot.docs[snapshot.docs.length - 1]
}
});
}
useBottomScrollListener(getNextPost); //스크롤이 바닥에 닿을때마다 문서 불러오기
useEffect(() => {
lastVisible = undefined; //lastVisible 초기화
getNextPost(); //최초 페이지 렌더링
},[]);
}
감사합니당