// ProductListPage.tsx
export default function ProductListpage() {
const [params] = useSearchParams();
const categoryId = params.get("categoryId") ?? undefined;
const { products } = useFetchProducts({ categoryId });
return (
<div>
<h2>Products</h2>
<Products products={products} />
</div>
);
}
// Products.tsx
export default function Products({ products }: ProductsProps) {
if (!products.length) {
return null;
}
return (
<Container>
<ul>
{products.map((product) => (
<li key={product.id}>
<Link to={`/products/${product.id}`}>
<Product product={product} />
</Link>
</li>
))}
</ul>
</Container>
);
}
// Product.tsx
export default function Product({ product }: ProductProps) {
return (
<div>
<Thumbnail src={product.thumbnail.url} />
<div>{product.name}</div>
<div>{numberFormat(product.price)}원</div>
</div>
);
}
view를 보여주는 컴포넌트들을 만들었다.
컴포넌트에서 선언적으로 훅을 이용해 데이터를 얻어다 쓰기만 하는 것.
const apiBaseUrl = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
export default function useFetchProducts() {
type Data = {
products: ProductSummary[],
};
const { data } = useFetch < Data > `${apiBaseUrl}/products`;
return {
products: data?.products ?? [],
};
}
상품 목록을 Store로 관리할 수 있다.
@singleton()
@Store()
export default class ProductsStore {
products: ProductSummary[] = [];
async fetchProducts() {
this.setProducts([]);
const { data } = await axios.get(`${apiBaseUrl}/products`);
const { products } = data;
this.setProducts(products);
}
@Action()
setProducts(products: ProductSummary[]) {
this.products = products;
}
}
export default function useFetchProducts(): {
products: ProductSummary[],
} {
const store = container.resolve(ProductsStore);
const [{ products }] = useStore(store);
useEffectOnce(() => {
store.fetchProducts();
});
return { products };
}