product
Fetch one product with its details, or a cursor-paged list of products from any source (latest, offers, category, search and more).
Use product for anything that shows products: a product page, a listing, a slider, a search.
import { getTwilightContext } from '@salla.sa/twilight-theme-engine/tanstack';
import { product } from '@salla.sa/twilight-theme-engine/api/product';
loader: () => {
const { queryClient } = getTwilightContext();
return queryClient.fetchQuery(product.queries.list({ source: 'offers' }));
},import { useQuery } from '@tanstack/react-query';
import { product } from '@salla.sa/twilight-theme-engine/api/product';
export function CategoryProducts({ categoryId }: { categoryId?: number }) {
const { data } = useQuery({
...product.queries.list({ source: 'categories', sourceValue: [categoryId!] }),
enabled: categoryId !== undefined,
});
const items = data?.items ?? [];
return <p>{items.length} products</p>;
}Methods
| Method | Parameters | Returns | Request | Login needed |
|---|---|---|---|---|
find | id: string | Promise<Product> | GET products/{id}/details?with[]=... (images, category, brand, options, skus, bundle and more) | No |
findOrThrow | id: string | Promise<Product> | Same as find | No |
list | params: ProductsListParams | Promise<ProductsListResult> | GET products?source=...&per_page=... | No (source: 'wishlist' and 'reorder' are customer-specific) |
ProductsListParams:
| Param | Description |
|---|---|
source | Required. One of brands, categories, json, landing-page, latest, offers, recently, related, selected, tags, top-rated, wishlist, search, sales, reorder, best_selling |
sourceValue | The ids the source reads (category, brand, tag or product ids), as an array such as [708738657]; sent as source_value[] |
keyword | The search words when source is 'search' |
page, cursor | Paging. Use cursor (from next); page is sent only if you set it |
perPage | Items per page, default 16 |
sort, filterable, filters | Sorting and filters |
signal | An AbortSignal |
The result is { items: Product[]; next: string | null; filters?: Filter[] }. Pass next back as cursor for the following page; it is null on the last page.
Queries
| Query | Key |
|---|---|
product.queries.detail(id) | ['products', 'detail', id, { scope }] |
product.queries.list(params) | ['products', 'list', params, { scope }] |
Both keys include the active scope (the customer's branch) because stock depends on it. Neither includes the locale; see Authentication and scope.
Gotchas
findthrows on an unknown id. In a loader usefindOrThrowto get a not-found page for a 404 or 410 (other errors still throw).- For
source: 'search'put the words inkeyword. Every other source needssourceValueas ids. - With
source: 'categories', acategory_identry infiltersreplacessourceValue. - Items returned by
listare remembered, soqueries.detail(id)can show the card data as placeholder while the full details load. - There are no mutations. Invalidate
['products']if the customer's branch changes.
See also
- wishlist, which reuses the list shape
- Product route and useProduct
- Authentication and scope