요구 사항
- Tablet에서 상단 네비게이션 영역의 좌우 여백은 50px을 유지합니다, 카드 리스트 영역의 좌우 최소 여백은 32px 입니다, 카드 컴포넌트의 최소 너비는 186px 입니다, 카드 리스트 영역이 줄어드는 것에 따라 카드 크기가 작아지다가 186px보다 작아질 때 하나의 행에 4개 → 3개씩 보이도록 합니다.
문제상황
- 렌더 시에 데이터 패칭 전 과정에서 아무런 요소가 없어 사용자가 요소와 페이지네이션의 존재를 알 수 없다.
- 반응형 요소 변화 시 요소 개수 오류
- (8개 -> 6개)
- (6개 -> 8개)
- (8개 -> 6개)
적용 사항
- Skeleton UI를 적용하여 렌더링 시 요소 위치를 사용자에게 미리 보여줌
- code
// before //... return ( <> <UserCard name={name} src={src} count={questionCount} /> </> ); }; export default SubjectCard;
// after // ... const shortName = name.length > 6 ? name.slice(0, 6) + '...' : name; return ( <> { isLoading ? ( <SkeletonUserCard /> ) : ( <UserCard name={shortName} src={src} count={questionCount} /> ) } </> ); }; export default SubjectCard;
- 미리보기
- code
- 최초 렌더링 시 8개/6개 API 호출하여 반응형 변경 시 추가적인 API 호출을 방지
- 페이지네이션 시 총 페이지 수 개산이 달라져 페이지네이션에서 오류가 남(미해결)
- code
-
// before // ... const SubjectListPagination = ({ order }: SubjectListPaginationProps) => { // ... useEffect(() => { setCurrentIndex(1); }, [order]); const handleSubjects = async ({ limit, offset, sort }: SubjectListParams) => { const { count, results } = await getSubjectList({ limit, offset, sort }); setSubjects(results); setMaxIndex(Math.ceil(count / pageSize)); }; useEffect(() => { const offset = pageSize * (currentIndex - 1); handleSubjects({ limit: pageSize, offset, sort: order }); }, [order, currentIndex, pageSize]); // ... }; export default SubjectListPagination;
-
// after // ... const useSubjectList = ({ order }: SubjectListFuncParams) => { // ... // 8 개일 때 상태 const { data: data8, isError: isError8, isSuccess: isSuccess8, } = useQuery({ queryKey: ['subjectList8', currentIndex, order], queryFn: () => handleQueryRequest(8), refetchOnWindowFocus: false, }); // 6 개일 때 상태 const { data: data6, isError: isError6, isSuccess: isSuccess6, } = useQuery({ queryKey: ['subjectList6', currentIndex, order], queryFn: () => handleQueryRequest(6), refetchOnWindowFocus: false, }); const handleCurrentIndex = (newValue: number) => { setCurrentIndex(newValue); }; // 에러 핸들링 및 로딩 처리 useEffect(() => { // ... const { count, results } = data8; setItemCount(count); setSubjects8(results); // ... }, [data8, isError8, isSuccess8]); // 에러 핸들링 및 로딩처리 useEffect(() => { //... const { count, results } = data6; setItemCount(count); setSubjects6(results); // ... }, [data6, isError6, isSuccess6]); // ...
미리보기
- tanstack React Query를 이용하여 API 통신 캐싱
- React Query의 패칭 방식을 이용하여 캐싱 내용을 미리 보여주고 API 통신 후, 비교하여 변동 사항이 있으면 리렌더링
- 페이지 당 최초 렌더링 이후 부드럽게 움직임 (해결)
- code
// useSubjectListQuery.ts
const useSubjectListQuery = ({
currentIndex,
order,
pageSize,
}: SubjectListQueryParams) => {
const handleQueryRequest = async (page: number) => {
// ...
return useQuery({
queryKey: ['subjectList', currentIndex, order, pageSize],
queryFn: () => handleQueryRequest(pageSize),
refetchOnWindowFocus: false,
gcTime: 1000 * 60 * 2,
staleTime: 1000 * 5,
});
// useSubjectList.ts
// ...
const { data, isError, isSuccess, isLoading } = useSubjectListQuery({
order,
currentIndex,
pageSize,
});
// ...
useEffect(() => {
if (isLoading) {
setSubjects(getDefaultArray(pageSize));
} else if (isSuccess) {
const { count, results } = data;
setItemCount(count);
setSubjects(results);
setCurrentIndex((prev) => {
return prev > Math.ceil(count / pageSize)
? Math.ceil(count / pageSize)
: prev;
});
} else if (isError) {
}
}, [data, isError, isSuccess]);
// ...
- 미리보기
개선 전 후 비교
초기 렌더링 레이아웃
반응형 레이아웃
- 6개 → 8개
- 8개 → 6개
느낀점
사실 별 것 아닌 내용이라고 넘어갈 수 있었지만, 이런 오류들을 고쳐보면서 당연하게 느꼈던 요소들이 모두 개발자가 꼼꼼하게 개발한 거구나라는 대단함을 느꼈다..
GitHub Link
반응형
'PROJECT > 에러핸들링' 카테고리의 다른 글
[LinkBrary] Next.js 쿠키 만들기 ( with. API Routes ) (2) | 2024.09.25 |
---|