🌱 문제 상황
마이페이지에서 내가 '리뷰 남긴 테마'와 '좋아요 누른 테마'로 구성된 탭을 눌렀을 때, 눌린 탭별로 테마 리스트가 업데이트되어야 합니다.
그러나 테스트 도중, 아래의 움짤처럼 한쪽 탭에 아무 값도 존재하지 않을 때(아래는 리뷰 남긴 테마가 0개이고, 좋아요 누른 테마가 2개인 경우), 한쪽 탭에 해당하는 리스트 값이 다른 탭에 남아있는 오류를 발견하였습니다.
기존에는 아래의 코드처럼 productMenuContents라는 배열로 메뉴 탭을 정의하고, 현재 선택된 메뉴 탭의 id값을 상태로 관리하였습니다.
그리고 메뉴 탭을 나타내는 버튼(<button>)을 클릭할 때마다 onClick 이벤트로 탭 id 상태값을 변화시키고,
useInfiniteQuery를 포함하는 파일에 쿼리키를 위한 파라미터로 메뉴 탭의 타입(type = 'reviewed' | 'favorite')을 전달해주었습니다.
const productMenuContents = [
{
id: 0,
title: '리뷰 남긴 테마',
type: 'reviewed',
},
{
id: 1,
title: '좋아요 누른 테마',
type: 'favorite',
},
]
export default function ProductCardList() {
const [activeMenu, setActiveMenu] = useState<number>(0);
const {
data: productList,
fetchNextPage,
refetch: refetchProductList,
} = useInfiniteUserProduct({ ..., type: productMenuContents[activeMenu].type });
const allProducts = productList?.pages.flatMap(page => page.list);
const handleProductMenuClicked = (selectedId: number) => {
setActiveMenu(selectedId)
};
return (
<section>
{// 테마 메뉴}
<div>
{productMenuContents.map(productMenuContent => (
<button
onClick={() => handleProductMenuClicked(productMenuContent.id)}
>
{productMenuContent.title}
</button>
))}
</div>
{// 테마 리스트}
<div>
{allProducts.map(product => (
<ProductCard key={product.id} productId={product.id} data={product} />
))}
</div>
</section>
);
}
🌱 해결 방법
처음에는 메뉴 탭이 변경될 때 메뉴에 알맞은 리스트 값이 제대로 업데이트되지 않는다고 생각하여
useEffect 안에 렌더링 될 테마 리스트 값을 리패치하는 함수를 두고, 의존성 배열에 선택된 메뉴 탭 상태를 넣어 메뉴 탭이 변경될 때마다 리패치가 이루어지도록 하였습니다.
useEffect(() => {
refetchProductList()
}, [activeMenu, refetchProductList]);
그러나 여기서 refetch() 함수는 기존의 데이터가 만료(stale) 상태일 때만 새로운 데이터를 가져옵니다.
이와 같은 이유로 만료 상태가 되기까지의 staleTime을 1분으로 설정해두었던 해당 프로젝트에서는
1분이 지나기 전에 메뉴 탭을 변경하는 경우 데이터가 새로 불러와지지 않았습니다.
따라서 쿼리키 자체를 제거하여 캐싱된 데이터를 삭제하고, 다시 새로운 데이터를 리패치하는 방법을 통해
사용자가 누른 메뉴 탭별로 테마 리스트가 업데이트되도록 구현하였습니다.
useEffect(() => {
queryClient.removeQueries({ queryKey: ['productType'] })
refetchProductList()
}, [queryClient, activeMenu, refetchProductList])
읽어주셔서 감사합니다:)