[미라클 TIL 9일차] next.js에서 react query
TIL 24. 01. 12
중고 물품 목록은 사용자에게 빠른 속도로 보여지기를 원한다. 필터가 있기는 하지만 실시간으로 변화하는 데이터가 아니기 때문에 SSG로 pre-rendering 하고자 했다.react query의 prefetchQuery 함수를 사용하여 애플리케이션에서 데이터를 미리 가져온다.
TODO
- 중고 물품 목록 표시
- 카테고리(견종 사이즈, 물품 종류)와 물품 상태(판매중, 판매완료)로 필터링
- 키워드 검색
- 정렬 (최신순, 인기순, 저가순, 고가순) - To Be Determined
<UsedGoods> // 페이지 컴포넌트 path="/used-goods"
<UsedGoodsListFilter /> // 카테고리, 물품 상태 필터
<UsedGoodsList list={list}> // 중고 물품 목록
<UsedGoodsItem item={item}/> // 중고 물품 아이템
<UsedGoodsItem />
</UsedGoodsList>
</UsedGoods>
UsedGoods
: 페이지(“/used-goods”). 데이터 Fetching하여 전달UsedGoodsListFilter
: 카테고리, 물품 상태로 필터링 (query string)UsedGoodsList
: 중고 물품 목록 표시UsedGoodsItem
: 중고 물품 아이템
UsedGoodsListFilter
에서 URL 변경 (server action 이용하여 redirect)
➡ UsedGoods
에서 params를 기준으로 data fetching
➡ API 응답 파싱하여 UsedGoodsList
로 전달
구현
// app/used-goods/page.tsx
import { UsedGoodsListFilter, UsedGoodsList } from './_components';
import { HydrationBoundary, QueryClient, dehydrate } from '@tanstack/react-query';
import { supabase } from '@/shared/supabase/supabase';
import { QueryData } from '@supabase/supabase-js';
const usedItemsWithCategoryAndCountQuery = supabase
.from('used_item')
.select(
`id, created_at, title, price, address, sold_out, photo_url, main_category (name), sub_category (name), chat_list ( count ), used_item_wish ( count )`
);
export type UsedItemsWithCategoryAndCount = QueryData<typeof usedItemsWithCategoryAndCountQuery>;
export const getUsedGooddsKey = 'used-goods';
export const getUsedGoods = async () => {
const { data } = await usedItemsWithCategoryAndCountQuery;
return data ?? [];
};
type SearchParams = { searchParams?: { [key: string]: string | undefined } };
const UsedGoods = async ({ searchParams }: SearchParams) => {
const { main, sub, search, page, orderBy } = searchParams || {};
const queryClient = new QueryClient();
await queryClient.prefetchQuery({
queryKey: [getUsedGooddsKey],
queryFn: getUsedGoods,
staleTime: 60 * 1000
});
return (
<div>
<h2>중고 물품 리스트</h2>
<UsedGoodsListFilter />
<HydrationBoundary state={dehydrate(queryClient)}>
<UsedGoodsList />
</HydrationBoundary>
</div>
);
};
export default UsedGoods;
// app/used-goods/_components/UsedGoodsList.tsx
'use client';
import { useQuery } from '@tanstack/react-query';
import { getUsedGoods } from '../page';
import UsedGoodsItem from './UsedGoodsItem';
const UsedGoodsList = () => {
const { data } = useQuery({ queryKey: ['used-goods'], queryFn: getUsedGoods });
return <div>{data?.map((goods) => <UsedGoodsItem key={goods.id} goods={goods} />)}</div>;
};
export default UsedGoodsList;
댓글남기기