2. 상품 목록

실습 레포

// 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를 보여주는 컴포넌트들을 만들었다.

중요한 건 이 컴포넌트들의 관심사가 아닌 비즈니스 로직, 그러니까

데이터를 불러오는 일은 useFetchProducts라는 훅에 의해 일어난다.

컴포넌트에서 선언적으로 훅을 이용해 데이터를 얻어다 쓰기만 하는 것.

const apiBaseUrl = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

export default function useFetchProducts() {
  type Data = {
    products: ProductSummary[],
  };

  const { data } = useFetch < Data > `${apiBaseUrl}/products`;

  return {
    products: data?.products ?? [],
  };
}

ProductsStore.ts

상품 목록을 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 };
}
  • useStore는 data, store가 든 배열을 반환하는 usestore-ts 훅이다.

  • hook은 api 서버가 어딨는지, url이 뭔지 알 필요가 없기 때문에 그 부분은 store로 옮긴 것.

  • hook은 데이터를 store에서 가져와 return 해주는 데에만 관심이 있다.

Last updated