안녕하세요
[UX] Channels 페이지네이션 적용 본문
적용 필요성: 등록된 채널이 많아짐에 따라 페이지 로드 비용이 커짐
초기에는 100~150개 가량의 채널이 등록되어 있었다.
지속적으로 활동을 하지 않거나 연관 없는 채널을 제외 했음에도
현재는 지속적으로 관련 채널이 늘어남에 따라서 350~450개 가량의 채널이 등록되어 있다.
한 번에 모든 데이터를 불러오고 렌더링 하기에는 너무 많기에
페이지네이션과 무한스크롤 중에서 고민하다가 페이지네이션을 택했다.
채널을 둘러보고 싶다면 1~2페이지의 연관성이 높은 채널과,
마지막 페이지엔 어떤 채널이 있는지를 주로 확인하기 때문이다.
exports.getSortedChannelsData = async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const pageSize = parseInt(req.query.pageSize) || 30;
const sorted_channels = await db.collection("sorted_channels");
const channelCount = await sorted_channels.countDocuments();
const sortedChannelList = await sorted_channels
.find({})
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
res.status(200).json({ channels: sortedChannelList, channelCount });
} catch (error) {
console.error(error);
res.status(500).json({ error: "Internal server error" });
}
};
page, pageSize 불러올 페이지와, 페이지 크기를 쿼리로 요청한다.
channelCount 최대 페이지를 설정하기 위해서 전체 채널의 갯수를 가져온다.
.skip 은 몇 개의 document를 건너뛸지를 정한다. 처음에는 페이지 1을 불러오므로 ((1-1) * 30) 처음부터 30개를 가져온다.
.limit은 몇 개의 document까지 가져올지를 정한다. skip한 이후부터 30개를 가져온다.
const NewChannel = () => {
const [channels, setChannels] = useState([]);
const [channelCount, setChannelCount] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
channels 렌더링할 채널 리스트를 배열에 담는다.
channelCount 채널의 수와 페이지 수를 표시하는데 이용된다.
currentPage 현재 페이지를 query로 보내기 위해, 현재 페이지를 나타내기 위해 쓰인다.
const requestChannelsAndSetStates = async (currentPage = 1, channelsPerPage = 30) => {
try {
const params = {
page: currentPage,
pageSize: channelsPerPage,
};
const response = await axios.get(API_ENDPOINTS.CHANNELS, { params });
const { channels, channelCount } = response.data;
setChannelsStates(channels, channelCount);
} catch (error) {
console.error("Error fetching data:", error);
}
};
const setChannelsStates = (channels, channelCount) => {
setChannels(channels);
setChannelCount(channelCount);
};
requestChannelsAndSetStates 쿼리를 보내고, 해당 페이지에 해당하는 채널 데이터를 받아온다
const paginationProps = {
channelCount,
currentPage,
setCurrentPage,
};
return (
<div className="channels container">
<div className="new-channel">
<Title subject={SUBJECT_VALUE} channelCount={channelCount} />
<div className="channel-list">
<Pagination {...paginationProps} />
<ul>
{channels.length ? (
channels.map((channel) => <ChannelItem key={channel.channelId} channel={channel} />)
) : (
<Loading />
)}
</ul>
<Pagination {...paginationProps} />
</div>
</div>
</div>
);
};
페이지네이션 컴포넌트에 필요한 프롭스를 전달한다
channelCount 페이지 숫자를 계산하기 위해 이용된다.
currentPage setCurrentPage 페이지 쿼리 요청과 현재 페이지를 표시하기 위해 이용된다.
const Pagination = ({ channelCount, setCurrentPage, currentPage }) => {
const pageNumbers = Array.from({ length: Math.ceil(channelCount / 30) }, (_, index) => index + 1);
const handleClickPageNumber = (number) => {
setCurrentPage(number);
window.scrollTo({ top: 0, behavior: "auto" });
};
return (
<nav className="page-navigator">
<ul className="page-list">
{pageNumbers.map((number) => {
return (
<li key={number} className="page-item">
<button
onClick={() => handleClickPageNumber(number)}
className={`${currentPage === number ? "active" : null} page-button`}
>
{number}
</button>
</li>
);
})}
</ul>
</nav>
);
};
export default Pagination;
페이지 숫자를 배열로 생성한다.
클릭 이벤트를 전달한다. => serCurrentPage(클릭한숫자)
'유튜브컨텐츠탐색-StelLife' 카테고리의 다른 글
[UX] 자바스크립트 메모리 누수를 경계하라 (0) | 2023.08.27 |
---|---|
[UX] 동적 width의 image가 로드되기 전과 후 레이아웃 다른 문제 해결 - 스켈레톤 (0) | 2023.08.23 |
[report:3] Live 상태 업데이트 실패 (0) | 2023.05.28 |
[report:2] 아이폰에서 다르게 보이는 문제 (0) | 2023.03.27 |
[report:1] 특정 채널 제외하기 (0) | 2023.03.27 |