git commit -m 'dev_#feat99 : ProductDetail Page InfiniteScroll error fixed'
[dev 8c7f23f] dev_#feat99 : ProductDetail Page InfiniteScroll error fixed
1 file changed, 92 insertions(+), 89 deletions(-)
하하 새벽4시까지 6시간을 인피니티 스크롤 오류고치는데 소모했다
그런데 작성한 코드 단 3줄,, 해결했을 때는 재밌고 기분이 좋았지만
6시간짜리 커밋을 날리고 내역을 확인한 순간 현타가 몰려왔다 그래도 해결했으니까..
서버에 등록된상품 개수는 총 28개, 한번에 받아오는 상품수 12개
총 28개를 받아오고 endMessage가 나와야 하는데 24개 출력후 무한로딩..
const [page, setPage] = useState(0);
=> const [page, setPage] = useState(1);
const { data, isLoading, fetchNextPage } = useInfiniteQuery(
["getProducts"],
async ({ pageParam = page - 1 }) => { //pageParam = page 에서 수정//
const response = await api.post("/cal/v1/product/", {
filter: [],
page: pageParam,
query: "",
size: size,
sort: [{ field: sortOption, option: sortOrder }], //SORT 기능//
});
},
{
refetchOnWindowFocus: false,
getNextPageParam: () => page,
}
);
pageParam 부분이 문제였다. page, setPage = useState(0) 서버쪽에서 page 시작 인덱스를
0번부터로 지정해두어 나도 당연히 0부터 시작을 했는데 이게 문제였던 듯 하다
그래서 useState 초기값을 1로 설정하고 위 코드와 같이 설정했더니 해결되어서 뭐가 문제였던건지 정말 어이가없었지만 console로 하나하나 찍어보니 답을 찾았다. pageParam 자체가 기본적으로 1부터 시작하게 권장되어 있기때문에 getNextPageParam 에서 변동되는 page값을 반환할 때 시작 인덱스가 0부터 시작이 되어 기능이 정상작동하지 않은것 같은데 허무하다..
이제 무한스크롤 기능을 구현했으니 상품 정렬필터를 만들 차례다.
useMutation을 사용하는 이유는 react-query로 fetching해온 데이터. 캐싱된 데이터를 변경해주고 변경사항을 UI에 동기화 할 때 아주 유용함. 별다른 동기화 처리를 해줄 필요가 없이 Mutation 함수만 잘 작성하면 동기화가 된다. 걱정되는게 한가지 있는데, InfiniteQuery에 Mutation이 사용이 될지는 잘 모르겠다,, useQuery와 InfiniteQuery 사용방식이 같으니 문제없이 사용되지 않을까 ?
const [sortOption, setSortOption] = useState("rating");
const [sortOrder, setSortOrder] = useState("desc");
const sortMutation = useMutation<void, unknown, [string, string]>(
async ([sortOption, sortOrder]) => {
await api.post("/cal/v1/product/", {
filter: [],
page: 0,
query: "",
size: size,
sort: [{ field: sortOption, option: sortOrder }],
});
},
{
onSuccess: () => {
queryClient.invalidateQueries(["getProducts", sortOption, sortOrder]);
},
}
).mutate;
코드 자체는 일반 비동기 API CALL 이랑 다를건 없다.
onSuccess: () => {
queryClient.invalidateQueries(["getProducts", sortOption, sortOrder]);
},
이 부분이 중요한데, post 요청 성공시 "getProducts" 라는 QueryKey를 가진 쿼리를 무효시켜준다. 즉, 정렬에 필요한 데이터 전송 성공시 쿼리를 무효화시켜 정렬된 쿼리를 다시 요청해온다는 것. 별다른 함수작성 없이 간단하게 데이터를 동기화해올 수 있다는게 큰 장점인 것 같다.
const handleSortChange = (option: string) => {
setPage(1);
if (sortOption === option) {
setSortOrder(sortOrder === "desc" ? "asc" : "desc");
} else {
setSortOption(option);
setSortOrder("desc");
}
sortMutation([option, sortOrder]);
};
정렬 후 Mutation 함수에 필요한 인자 전달 및 page값 초기화
page값을 초기화 해주는 이유는 정렬된값들을 받아올 때 이미 스크롤된 데이터의 page값을 그대로 사용하게되는 것을 방지하기 위해서 초기화 해주어야한다.
<Button variant={sortOption === "price" ? "contained" : "outlined"}
onClick={() => handleSortChange("price")}
>
가격순 {sortOption === "price" && sortOrder === "desc" && "▼"}
{sortOption === "price" && sortOrder === "asc" && "▲"}
</Button>
UI는 나중에 고치는걸로 하고 테스트 해보면
잘 작동한다
GITHUB : https://github.com/casealot/casealot-frontend
자만하지 말자.. 컴퓨터는 거짓말 하지 않는다
몇시간을 붙잡고있어도 해결이 안되는 문제들은 대부분 어렵다기 보다는 익숙하지 않은 기능을 접했을 때 발생하는 것 같다. 이번 경우는 함수를 작성하면서 어려웠다기 보다는 맞게 했는데 왜 안되지? 안될 이유가 없는데 안되네 등의 자만 때문이었 던 것 같다. 공식문서에서 설명해주는 내용들을 꼼꼼히 읽어보고 console을 찍어가며 제공되는 기능들을 보다 더 자세히 알아보고 이해하는 것을 더 우선시 하고 코드를 작성해야 오류해결에 쓰는 시간을 줄일 수 있을 것 같다.