일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- recoil
- webpack
- CI/CD
- app router
- CORS
- dfs
- 인터섹션
- TS
- async/await
- 반공변성
- tailwind
- 무한 스크롤
- autosize
- Cypress
- SSR
- ESlint
- map
- 결정 알고리즘
- 타입 좁히기
- 공변성
- RTK Query
- 이분 검색
- 호이스팅
- Jest
- 태그된 유니온
- 리터럴 타입
- React
- useAppDispatch
- 투포인터
- Promise
Archives
- Today
- Total
짧은코딩
무한 스크롤 값 저장 방식 수정 with 공식 사이트 본문
반응형
이전 구현 방식
https://shortcoding.tistory.com/534
저번에는 무한 스크롤에서 데이터를 불러오고 데이터 저장을
items를 따로 만들어서 하였다.
이번에는 공식 사이트에서 준 예시를 보고 구현해 보겠다. 전체 상품을 불러오는 페이지를 구현하는 것은 쉬웠다. 하지만 검색 상품을 가져오는 페이지에서 설정 방법이 좀 달랐다.
구현 방법
-참고 사이트
https://redux-toolkit.js.org/rtk-query/api/createApi#merge
우선 이 공식 문서 사이트를 보고 구현했다.
-핵심 내용
// Only have one cache entry because the arg always maps to one string
serializeQueryArgs: ({ endpointName }) => {
return endpointName
},
// Always merge incoming data to the cache entry
merge: (currentCache, newItems) => {
currentCache.push(...newItems)
},
// Refetch when the page arg changes
forceRefetch({ currentArg, previousArg }) {
return currentArg !== previousArg
},
- serializeQueryArgs: 이 설정은 endpoint의 이름을 기억했다가 그 데이터를 캐싱의 키 값 역할을 한다. 검색 페이지에서 이 부분을 건드려야 했다.
- merge: 이 설정은 현재 캐싱된 데이터와 새로 불러온 데이터를 합쳐주는 부분이다. 이 부분에서 데이터를 수정하려할때 immer에러가 발생한 것을 보면 immer를 사용하여 데이터 수정을 해주는 것 같다.
- forceRefetch: 이 부분은 페이징 인수가 변경되면 이를 감지하고 새로 refetch를 해주는 역할이다.
모든 상품 불러오는 페이지
- itemApi.ts에서 이렇게 설정하여 모든 아이템들을 페이징하여 불러왔다.
- 새로운 값을 불러오면 merge에서 currentCache에 값들을 합쳤다.
-MainItem.tsx
const MainItem = () => {
const [page, setPage] = useState(0);
const { data, error, isLoading } = itemsApi.useGetAllItemsQuery(page);
const [finalPage, setFinalPage] = useState(false);
const { ref, inView } = useInView();
useEffect(() => {
if (inView && !finalPage) {
setPage((prev) => prev + 1);
}
}, [inView, finalPage]);
useEffect(() => {
if (data) {
setFinalPage(data.finalPage);
}
}, [data]);
return (
<Wrapper>
<TitleContainer>
<h2>전체 상품</h2>
</TitleContainer>
{error && <div>새로고침하여 주세요.</div>}
{isLoading && <div>로딩중...</div>}
{data && (
<ItemContainer>
{data?.items?.map((item: item, index) => {
return (
<Link
to={`/eachitem/${item.itemId}`}
key={item.itemId}
ref={data.items.length - 5 === index ? ref : null}
>
<ItemBox>
<ItemImg>
<img src={item.imageUrl} alt={"상품 사진"} />
</ItemImg>
<ItemInfo>
<ItemName>{item.itemName}</ItemName>
<span>{item.category}</span>
<ItemPrice>{item.basicPrice}원</ItemPrice>
</ItemInfo>
</ItemBox>
</Link>
);
})}
</ItemContainer>
)}
</Wrapper>
);
};
이 코드를 통해 최종적으로 구현하였다.
상품 검색 페이지
- 상품 검색 페이지에서는 serializeQueryArgs에서 queryArgs 인자를 추가하여 활용했다.
- url params인 word를 활용하여 검색하는 상품의 이름이 변경되면 데이터 캐시를 다시 하도록 했다.
- merge에서는 검색한 상품의 결과가 없을 수도 있기 때문에 타입 가드를 사용해서 구현했다.
-SearchItem.tsx
const SearchItem = () => {
const path = useLocation();
const [page, setPage] = useState(0);
const [finalPage, setFinalPage] = useState(false);
const { ref, inView } = useInView();
const { data, error, isLoading } = itemsApi.useGetSearchItemsQuery({
word: decodeURI(path.pathname.slice(12)),
page,
});
useEffect(() => {
if (inView && !finalPage) {
setPage((prev) => prev + 1);
}
}, [inView, finalPage]);
useEffect(() => {
if (data && "finalPage" in data) {
setFinalPage(data.finalPage);
}
}, [data]);
useEffect(() => {
setPage(1);
}, [path]);
return (
<Wrapper>
<TitleContainer>
<h2>검색결과</h2>
</TitleContainer>
{error && <div>새로고침하여 주세요.</div>}
{isLoading && <div>로딩중...</div>}
{data && "message" in data && <NullData />}
{data && "finalPage" in data && (
<ItemContainer>
{(data as ItemPaging)?.items?.map((item: item, index) => {
return (
<Link
to={`/eachitem/${item.itemId}`}
key={item.itemId}
ref={
(data as ItemPaging)?.items?.length - 5 === index ? ref : null
}
>
<ItemBox>
<ItemImg>
<img src={item.imageUrl} alt={"상품 사진"} />
</ItemImg>
<ItemInfo>
<ItemName>{item.itemName}</ItemName>
<span>{item.category}</span>
<ItemPrice>{item.basicPrice}원</ItemPrice>
</ItemInfo>
</ItemBox>
</Link>
);
})}
</ItemContainer>
)}
</Wrapper>
);
};
상품 검색 페이지는 최종적으로 이렇게 구현했다.
-상품 검색 페이지 구현 영상
반응형
'wayc 이커머스 프로젝트' 카테고리의 다른 글
스크롤 맨 위로 올리기 with react-custom-scrollbars (1) | 2024.01.07 |
---|---|
MSW1 사용 중 Warning: captured a request without a matching request handler (2) | 2024.01.03 |
전체 상품 불러오기 무한 스크롤 구현 with react-intersection-observer (0) | 2023.12.26 |
Webpack의 HMR과 자동 새로고침 현상 (0) | 2023.11.12 |
로그인 전략 with Cookie (0) | 2023.10.24 |
Comments