UNPKG

@techsio/storefront-data

Version:

Medusa-first storefront data layer built on TanStack Query.

238 lines (182 loc) • 5.71 kB
--- name: use-catalog-and-product-read-flows description: > Load this skill when reading products, catalog listings, categories, collections, or regions from @techsio/storefront-data through storefront.hooks.products, storefront.hooks.catalog, and the related read hooks. Use it for region-aware inputs, query-option helpers, and suspense usage that waits until required params actually exist. type: core library: "@techsio/storefront-data" library_version: "0.1.0" requires: - setup-storefront-platform-in-next-app sources: - "TechsioCZ/new-engine:libs/storefront-data/README.md" - "TechsioCZ/new-engine:libs/storefront-data/src/products/hooks.ts" - "TechsioCZ/new-engine:libs/storefront-data/src/products/medusa-service.ts" - "TechsioCZ/new-engine:libs/storefront-data/src/catalog/hooks.ts" - "TechsioCZ/new-engine:libs/storefront-data/src/catalog/medusa-service.ts" - "TechsioCZ/new-engine:libs/storefront-data/src/collections/hooks.ts" - "TechsioCZ/new-engine:libs/storefront-data/src/categories/hooks.ts" - "TechsioCZ/new-engine:libs/storefront-data/src/regions/hooks.ts" --- ## Setup Start from the preset-owned read hooks. Keep region inputs explicit in the app code that knows them. ```tsx "use client" import { storefront } from "@/src/lib/storefront" export function ProductGrid({ regionId, countryCode, }: { regionId: string countryCode: string }) { const query = storefront.hooks.products.useProducts({ region_id: regionId, country_code: countryCode, limit: 24, }) if (query.isLoading) return <div>Loading...</div> return ( <ul> {query.products.map((product) => ( <li key={product.id}>{product.title}</li> ))} </ul> ) } ``` ## Core Patterns ### Filter catalog listings through the shared catalog hook ```tsx "use client" import { storefront } from "@/src/lib/storefront" export function CategoryListing({ regionId, countryCode, categoryId, }: { regionId: string countryCode: string categoryId: string }) { const query = storefront.hooks.catalog.useCatalogProducts({ region_id: regionId, country_code: countryCode, category_id: [categoryId], limit: 24, }) if (query.isLoading) return <div>Loading...</div> return <div>{query.products.length} products</div> } ``` ### Use suspense detail hooks only after route and region params are ready ```tsx "use client" import { storefront } from "@/src/lib/storefront" export function ProductHero({ handle, regionId, countryCode, }: { handle: string regionId: string countryCode: string }) { const query = storefront.hooks.products.useSuspenseProduct({ handle, region_id: regionId, country_code: countryCode, }) if (!query.product) return null return <h1>{query.product.title}</h1> } ``` ### Pull option objects from the hooks when SSR or manual cache work is needed ```ts import { storefront } from "@/src/lib/storefront" const listQuery = storefront.hooks.products.getListQueryOptions({ region_id: "reg_123", country_code: "cz", limit: 24, }) const detailQuery = storefront.hooks.products.getDetailQueryOptions({ handle: "classic-tee", region_id: "reg_123", country_code: "cz", }) ``` Use the hook surface for most reads. Use query-option helpers when SSR, manual prefetch, or loader integration needs the exact query shape. ## Common Mistakes ### CRITICAL Suspense before params exist Wrong: ```tsx const query = storefront.hooks.products.useSuspenseProduct({ handle: params.handle, region_id: regionId, }) ``` Correct: ```tsx const query = storefront.hooks.products.useProduct({ handle: params.handle, region_id: regionId, enabled: Boolean(params.handle && regionId), }) ``` Suspense variants assume required inputs already exist. During routing or region bootstrap they throw instead of waiting. Source: `libs/storefront-data/src/products/hooks.ts`, `libs/storefront-data/src/categories/hooks.ts`, `libs/storefront-data/src/collections/hooks.ts` ### HIGH App-local `useQuery` wrappers for Medusa reads Wrong: ```ts const products = useQuery({ queryKey: ["products", params], queryFn: () => sdk.store.product.list(params), }) ``` Correct: ```ts const products = storefront.hooks.products.useProducts(params) ``` App-local wrappers duplicate the normalization, query-key rules, and bug fixes that the preset is supposed to centralize. Source: `libs/storefront-data/AGENTS.md`, maintainer interview ### HIGH Dropping region-sensitive inputs Wrong: ```ts storefront.hooks.catalog.useCatalogProducts({ category_id: ["cat_123"], limit: 24, }) ``` Correct: ```ts storefront.hooks.catalog.useCatalogProducts({ category_id: ["cat_123"], region_id: "reg_123", country_code: "cz", limit: 24, }) ``` Product and catalog services normalize region-aware inputs. Missing them fragments payload shape and cache identity across the storefront. Source: `libs/storefront-data/src/catalog/medusa-service.ts`, `libs/storefront-data/src/products/medusa-service.ts` ### HIGH Assuming custom field defaults come from the library Wrong: ```ts storefront.hooks.products.useProduct({ handle: "classic-tee", region_id: "reg_123", }) ``` Correct: ```ts storefront.hooks.products.useProduct({ handle: "classic-tee", region_id: "reg_123", fields: "+variants,+metadata", }) ``` The README explicitly keeps product field defaults in the local storefront composition layer. Do not assume a universal default bundle for every storefront. Source: `libs/storefront-data/README.md`, `libs/storefront-data/src/products/types.ts` See also: `configure-pagination-prefetch-and-cache-policy` for prefetch behavior and normalized query-key rules.