티스토리 뷰
사용자 페이지에 접속 시 사용자가 작성한 Comments와 좋아요를 누른 Liked Place를 표시한다.
각각의 데이터는 모두 페이지네이션을 사용해 표시했다.
Comments 페이지네이션
comments 데이터를 가져올 때 offset(from)에서 시작해 offset(from+to)에서 끝나는 방식으로 쿼리 결과를 제한한다.
from및 to 값은 0부터 시작하며 이 범위 내의 레코드만 반환한다.
이때 쿼리 순서를 존중하며 order 절이 없으면 범위가 예상치 못하게 동작할 수 있다.
export const getCommentsById = async(user_id:string,page:number=1, pageSize:number = 10)=>{
const supabase =await createServerSideClient();
const result = await supabase.from('comments')
.select('*',{count: 'exact'}) // count를 추가로 전달->정확한 행 수를 리턴
.is('deleted_at',null)
.eq('user_id',user_id)
.order('created_at',{
ascending:false // 내림차순 정렬
})
.range((page-1)*pageSize, page*pageSize-1); // 10개씩 가져오기
return {data:result.data , count:result.count};
};
comments controller 훅에서 api를 요청할 때 page가 변화될 때마다 요청을 보낼 수 있도록 구현했다.
export const useCommentsById = (user_id:string, pageSize:number=10) =>{
const [loading, setLoading] = useState(false);
const [comments, setComments] = useState<TypeComments[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const onGetCommentsById =useCallback(
async(page:number) =>{
setLoading(true);
try{
const result= await getCommentsById(user_id,page,pageSize);
if(result?.data){
setComments(result.data);
setTotal(result.count || 0);
}
} catch(error){
console.log(error);
} finally{
setLoading(false);
};
},[user_id, pageSize])
useEffect(()=>{
onGetCommentsById(page);
},[user_id, page, onGetCommentsById]);
return {loading, comments, total, page, pageSize, setPage}
}
+ 페이지 버튼 표시하기
comments 데이터를 불러와 데이터가 존재하는 페이지 수 만큼의 버튼을 표시하고 버튼을 클릭하면 해당 범위에 따른 데이터를 가져오도록 구현했다.
useCommentsById를 호출해 받아온 total과 pageSize를 사용해 총 페이지 수를 구한다.
const totalPages = Math.ceil(total / pageSize);
총 페이지 수 만큼 요소가 들어있는 배열을 만든다. (ex. totalPages =2 -> [1,2])
Array.from 메소드를 사용해 구현했다.
첫 번째 인자로 배열로 변환할 순회 가능 또는 유사 배열 객체를 전달하고 두 번째 인자로 맵핑 함수를 전달한다.
{Array.from({ length: totalPages }, (_, idx) => (
<button key={idx} onClick={() => setPage(idx + 1)}>
{idx + 1}
</button>
))}
버튼 클릭 이벤트로 page를 변화시켜 api 요청이 이루어지도록 구현했다.
Liked Place 페이지네이션
liked-place의 경우 comments와 동일한 코드로 작성할 시 제대로 작동하지 않는다.
rang 메소드는 테이블의 각 행을 기준으로 범위를 설정하기 때문이다!
liked-place 데이터는 liked_place 필드 내에 존재하기 때문에 요소의 수에는 영향을 줄 수 없다.
⇨ liked-place 필드 데이터를 그대로 가져와 커스텀 훅에서 페이지네이션을 진행했다.
export const useLikedPlacePagination = (userId:string, pageSize:number=6) =>{
const [loading, setLoading] = useState(false);
const [likedPlace, setLikedPlace] = useState<TypePlaceLike[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const onGetLikedPlacePagination =useCallback(
async(page:number) => {
setLoading(true);
try {
const result = await getLikedPlacePagination(userId);
if(result.data){
const allLikedPlaces =result.data[0].liked_place as TypePlaceLike[];
setTotal(allLikedPlaces.length);
const paginatedPlaces = allLikedPlaces.slice((page - 1) * pageSize, page * pageSize);
setLikedPlace(paginatedPlaces);
}
} catch (error) {
console.log(error)
} finally {
setLoading(false);
}
},[userId, pageSize])
useEffect(()=>{
onGetLikedPlacePagination(page);
},[userId, page, onGetLikedPlacePagination]);
return {loading, likedPlace, total, page, pageSize, setPage}
}
전체 데이터를 가져와 slice 메소드를 사용해 데이터를 잘라 요청한 페이지의 수 만큼만 전달한다.
참고 사이트: https://supabase.com/docs/reference/javascript/range
'코딩 > 프로젝트' 카테고리의 다른 글
[Supabse] OAuth 로그인 후 profile 데이터 추가 (0) | 2025.01.22 |
---|---|
[개인 프로젝트] 풀 페이지 스크롤링 구현하기(+ 네비게이션바) (0) | 2024.01.05 |
[개인 프로젝트] 투두 다이어리(feat.투두 date 관리하기) (0) | 2023.12.12 |
[개인 프로젝트] 투두 다이어리 (feat.Redux-Toolkit으로 여러 개의 상태 관리하기) (0) | 2023.12.11 |
[개인 프로젝트] - Holiday Calendar 리팩토링 (React Query) (0) | 2023.06.02 |
- Total
- Today
- Yesterday
- 부트캠프
- React
- 데이터요청
- 정처기필기
- HTML
- 오블완
- nextjs
- 프론트엔드
- 클론코딩
- 로컬 저장소
- cdd
- React.JS
- 개발
- 번들링
- 프레임워크
- javascript
- 보안
- 띵동코딩
- Next.js
- styled-component
- 자바스크립트
- 웹팩
- 코드스테이츠
- useRef
- 티스토리챌린지
- 타입스크립트
- 인증
- 상태관리
- git 오류
- css
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |