[최종 사용: useInfiniteQuery]
[사용]
* DB : 파이어베이스
* React Query
* TypeScript
[로직]:더보기 기능 (관리자용)
// 1. itemPerRow : 기본 개수 (4 개)
// 2. startIndex : 배열 slice에서 사용되는 시작 index (값: 0)
// 3. cnt : 더보기 클릭시 개수 (cnt = 1 : 기본 4개 보여주기 위해서 1로 시작)
// 3. endIndex : startIndex + itemPerRow * cnt
// 4. DisplayItem : 배열(관리자/selectedCategory).slice(startIndex,endIndex)
// 5. 더보기 클릭시 cnt ++
[구현]
[usePaginatedItem.ts]-- 훅
import { useEffect, useState } from 'react';
export default function usePaginatedItem(data: PostType[], itemPerRow: number) {
const [cnt, setCnt] = useState<number>(1);
const [displayData, setDisplayData] = useState<PostType[]>([]);
useEffect(() => {
const endIndex = itemPerRow * cnt;
setDisplayData(data.slice(0, endIndex));
}, [data, cnt]);
useEffect(() => {
// data가 변경될 때 cnt를 1로 초기화
setCnt(1);
}, [data]);
const showMore = () => setCnt((prev) => prev + 1);
return { displayData, showMore };
}
[ViewAllBody.tsx]
//커스텀 훅 : 더보기 기능 (관리자용)
const ITEM_PER_ROW = 4;
const { displayData: displayAdminData, showMore: showMoreAdmin } = usePaginatedItem(
adminQuery.data || [],
ITEM_PER_ROW
);
//커스텀 훅 : 더보기 기능 (사용자용)
const { displayData: displayUserData, showMore: showMoreUser } = usePaginatedItem(
selectCategory || [],
ITEM_PER_ROW
);
return (
<St.ContentsWrapper>
<St.Contents>
{displayAdminData?.map((item) => (
<St.Content key={item.id}>
<p>{item.title}</p>
<p>{item.content}</p>
<p>{item.category}</p>
</St.Content>
))}
</St.Contents>
</St.ContentsWrapper>
<button onClick={showMoreAdmin}>더보기...</button>
1. 코드 구현
[ViewAllBody.tsx]
const itemPerRow = 4;
const startIndex = 0;
let endIndex = 0;
const [cnt, setCnt] = useState(1);
const [DisplayAdminItem, setDisplayAdminItem] = useState<PostType[]>([]);
useEffect(() => {
if (adminQuery.data) {
endIndex = startIndex + itemPerRow * cnt;
setDisplayAdminItem(adminQuery.data.slice(startIndex, endIndex));
}
}, [adminQuery.data, cnt]);
//더보기 버튼
const handleShowMoreClick = () => {
setCnt((prev) => prev + 1);
};
▶ 관리자용 & 사용자 카테고리별로 사용해야하기에 코드 중복을 줄이기 위해 커스텀 훅으로 변경 필요해보임.
"커스텀 훅으로 개선"
[usePaginatedItem.ts]
import { useEffect, useState } from 'react';
export default function usePaginatedItem(data: PostType[], itemPerRow: number) {
const [cnt, setCnt] = useState<number>(1);
const [displayData, setDisplayData] = useState<PostType[]>([]);
useEffect(() => {
const endIndex = itemPerRow * cnt;
setDisplayData(data.slice(0, endIndex));
}, [data, cnt]);
const showMore = () => setCnt((prev) => prev + 1);
return { displayData, showMore };
}
▶ 데이터와 한줄에 표시될 숫자 매개변수로 받기
▶ cnt 초기값은 1
▶ 데이터 : 관리자 게시물 / 사용자 게시물 ( 4가지 카테고리 )
▶ useEffect()에서 선택된 데이터를 slice로 보여주는 개수 정하기 (데이터&cnt 값을 dependency array로 설정)
▶ showMore은 더보기 클릭시 cnt 증가
[문제]
[ViewAllBody.tsx]
const { displayData: displayUserData, showMore: showMoreUser } = usePaginatedItem(selectCategory || [], ITEM_PER_ROW);
//버튼 클릭시 해당 카테고리 선택
const handleButtonsClick = (category: PostType[] | undefined) => {
if (category) {
setSelectCategory(category);
} else {
setSelectCategory([]);
}
};
<St.ButtonWrapper>
<St.Button onClick={() => handleButtonsClick(knowHowQuery.data)}>친환경 노하우</St.Button>
<St.Button onClick={() => handleButtonsClick(recommendQuery.data)}>제품 추천</St.Button>
<St.Button onClick={() => handleButtonsClick(shareQuery.data)}>제품 나눔</St.Button>
<St.Button onClick={() => handleButtonsClick(habitQuery.data)}>습관 인증</St.Button>
</St.ButtonWrapper>
▶ 버튼 클릭할때마다 동일 함수를 사용하여 매개변수에 받는 카테고리로 지정하여 데이터를 전달하였는데
같은 커스텀 훅을 사용하니, 같이 동작함
(예, 친환경노하우 카테고리에서 "더보기" 클릭하면 제품추천은 이미 데이터가 "더보기" 기능이 적용되어있음)
[개선]
[usePaginatedItem.ts]
useEffect(() => {
// data가 변경될 때 cnt를 1로 초기화
setCnt(1);
}, [data]);
▶ 간편하게 수정하기 위해서 커스텀 훅에서 data가 변경될때 cnt 값을 1로 초기화
=> 더보기 : 선택된 데이터를 slice로 보여주는 개수 정하기가 초기화 되어 초기 4개만 출력됨
끝.