메모 페이지에서, 무한스크롤을 구현할 때 react-query를 쓰는 이유로 꽤 오랜 시간을 날렸다.
useQuery첫번째 array의 두번째 인자부터는 dependency인데, 이부분을 잘 숙지하지 못해 useEffect와 혼용한 탓에 조금 헤맸다.
결론적으로, react-intersection-observer
라이브러리에서 inView
값을 useQuery의 deps안에 넣어주는 게 덜 복잡했고, 백엔드에서 hasNextPage혹은 totalCount값으로 모든 메모의 갯수를 넘겨주는 게 필요하기도 했다.
import React, { useState } from "react";
import { useInView } from "react-intersection-observer";
import { useQuery } from "react-query";
import { useRecoilState } from "recoil";
import { memoBoard, memoContent, memoWrapper } from "./style";
import { rcMemoPage } from "../../store/atoms/memoAtoms";
import { instance } from "../../config";
/** @jsxImportSource @emotion/react */
function MemoContainer() {
const [memoList, setMemoList] = useState([]);
const [pageNum, setPageNum] = useRecoilState(rcMemoPage);
const [ref, inView] = useInView();
const memo = useQuery(
["getMemo", pageNum, inView],
async () => {
const response = await instance.get(`/api/memo/${pageNum}`);
if (response.data.length === 0) return;
setMemoList([...memoList, ...response.data.memoList]);
if (inView && response.data.totalCount - pageNum * 9 > 0) {
setPageNum(pageNum + 1);
}
return response.data;
},
{
retryOnMount: false,
refetchOnWindowFocus: false,
},
);
return (
<div css={memoWrapper}>
<div css={memoBoard}>
<div className="memo-scroll-board">
{memoList.map((e, i) => {
return (
<div key={e.memoContent + Math.random()} css={memoContent(i)}>
<p className="author-label">{e.author}</p>
<div className="content-area">
<pre>{e.memoContent}</pre>
</div>
<p className="date-label">{e.createdDate}</p>
</div>
);
})}
{memo.isSuccess && <div style={{ height: "1px" }} ref={ref} />}
</div>
</div>
</div>
);
}
export default MemoContainer;
수정한 코드 전문