Hooks: useProductBundles to useSubmitReview
The hooks of @poltura/theme-sdk/product, useProductBundles to useSubmitReview.
On this page
import { … } from '@poltura/theme-sdk/product';useProductBundles
The bundles that include the given products, by product id.
useProductBundles(by: {
readonly productIds: readonly string[];
}, options?: Omit<QueryOptions, 'suspense'>): QueryResult<ReadonlyMap<string, readonly Bundle[]>>Parameters
by: { readonly productIds: readonly string[]; }: The products to find bundles for.options?: Omit<QueryOptions, 'suspense'>: Whether the read runs, and whether it keeps the previous answer while loading.
Returns: A map from each product id to its bundles; a product without bundles is absent.
Example
import { useProductBundles } from '@poltura/theme-sdk/product';
export function BundleCount({ productId }: { productId: string }) {
const { data } = useProductBundles({ productIds: [productId] });
return <span>{data?.get(productId)?.length ?? 0}</span>;
}useRelatedProducts
Related product cards: the merchant's picks, then automatic recommendations when switched on, then popular products of the category and the store.
useRelatedProducts(query: {
readonly limit?: number;
} | undefined, options: SuspenseQueryOptions): SuspenseQueryResult<readonly ProductCard[]>
useRelatedProducts(query?: {
readonly limit?: number;
}, options?: QueryOptions): QueryResult<readonly ProductCard[]>The store's most popular products fill what the picks, the automatic recommendations and the category leave free, and outside a product. The picks are read from the nearest product, so place the code inside the product page or a ProductScope. useProducts is unchanged: a section that still reads it lists exactly what it asks for.
Parameters
query: { readonly limit?: number; } | undefined: How many cards to return:limit, at most this many, 8 when omitted.options: SuspenseQueryOptions: Suspense, idling and keeping the previous answer while new inputs load.
Returns: The cards under "You may also like" for the nearest product, each product once; the product itself is never among them, and a pick that is hidden, unlisted or unpublished is left out.
Example
import { useRelatedProducts } from '@poltura/theme-sdk/product';
export function Related() {
const { data } = useRelatedProducts({ limit: 4 }, { suspense: true });
return <ul>{data.map((card) => <li key={card.id}>{card.title}</li>)}</ul>;
}useWishlist
The shopper's favourites: how many, which products, and a toggle. A signed-in shopper's list lives in their account and a guest's in the browser.
useWishlist(): WishlistStateUse WishlistButton for a plain heart; this hook is for a theme that draws its own.
Returns: The favourites, up to date as products are saved and removed anywhere on the page.
Example
import { useWishlist } from '@poltura/theme-sdk/product';
export function SavedCount() {
const { enabled, count } = useWishlist();
return enabled ? <span>{count}</span> : null;
}useOptionalProductPage
The product page's view, or null where no product page is drawn, such as a product shown inside another page.
useOptionalProductPage(): ProductPageView | nullReturns: The page's product, trail, highlights, specifications, guides, warranty, safety, coverage and reviews, or null.
Example
import { useOptionalProductPage } from '@poltura/theme-sdk/product';
export function Highlights() {
const page = useOptionalProductPage();
if (page === null || page.highlights.length === 0) return null;
return <p>{page.highlights.join(', ')}</p>;
}useProductPage
The product page with everything it shows beyond the product: the trail, highlights, specifications, guides, warranty, safety, coverage and the first reviews.
useProductPage(): ProductPageViewThrows outside the product page; place it under the product page's main section.
Returns: The page's view.
Example
import { useProductPage } from '@poltura/theme-sdk/product';
export function Highlights() {
const { highlights } = useProductPage();
return (
<ul>
{highlights.map((line) => (
<li key={line}>{line}</li>
))}
</ul>
);
}useProductTabs
The tabs the nearest product page shows, in the merchant's order.
useProductTabs(): readonly ProductTab[]A built-in tab with nothing to show for the product, a text tab without words and a table tab whose table the product does not have are left out, so every tab has something to draw. A store that never arranged its tabs gets the four built-in ones.
Returns: The tabs; empty outside a product page or when there is nothing to show.
Example
import { ProductTabContent, useProductTabs } from '@poltura/theme-sdk/product';
export function AllTabs() {
return useProductTabs().map((tab) => (
<section key={tab.id}>
<h3>{tab.label}</h3>
<ProductTabContent tab={tab} />
</section>
));
}useProductTableLinks
The nearest product's link tables, sorted onto its variant picker options.
useProductTableLinks(): ProductTableLinksReturns: The tables per option and the ones left over.
Example
import { ProductTableLink, useProductTableLinks } from '@poltura/theme-sdk/product';
export function SizeGuides() {
const links = useProductTableLinks();
return links.standalone.map((table) => <ProductTableLink key={table.id} table={table} />);
}useProductTables
The tables attached to the nearest product, optionally only those the merchant placed one way.
useProductTables(placement?: ProductTablePlacement): readonly ProductTable[]Parameters
placement?: ProductTablePlacement: Keeps the tables placed as a link, a tab or a section; every table when omitted.
Returns: The tables, strongest first; empty when the product has none.
Example
import { ProductTableView, useProductTables } from '@poltura/theme-sdk/product';
export function SizeTables() {
return useProductTables('section').map((table) => (
<ProductTableView key={table.id} table={table} />
));
}useReviews
The reviews of one or several products, one page at a time, with the review score over all of them.
useReviews(by: ReviewsBy, page?: PageRequest, options?: Omit<QueryOptions, 'suspense'>): QueryResult<ReviewPage>Parameters
by: ReviewsBy: Which products' reviews to read.page?: PageRequest: Which page to read and how many reviews it holds; the first three reviews by default.options?: Omit<QueryOptions, 'suspense'>: Whether the read runs, and whether it keeps the previous page while the next loads.
Returns: The page of reviews, newest first, once it loads.
Example
import { useReviews } from '@poltura/theme-sdk/product';
export function LatestReviews({ productId }: { productId: string }) {
const { data } = useReviews({ productId }, { limit: 5 });
return (
<ul>
{data?.reviews.map((review) => (
<li key={review.id}>
{review.title} {review.sourceLabel}
</li>
))}
</ul>
);
}useSubmitReview
Sending a shopper's review of a product, with the bot check and the refresh of the shown reviews.
useSubmitReview(): SubmitReviewStateThe bot check and the moderation are host-owned: a review lands in the merchant's approval queue unless it carries an invitation code.
Returns: The submit action and where the last send stands.
Example
import { useSubmitReview } from '@poltura/theme-sdk/product';
export function QuickReview({ productId, productHandle }: { productId: string; productHandle: string }) {
const review = useSubmitReview();
return (
<button
type='button'
disabled={review.status === 'submitting'}
onClick={() =>
void review.submit({
productId,
productHandle,
author: 'Anna',
email: 'anna@example.com',
rating: 5,
title: 'Lovely',
body: 'Exactly as described, fast delivery.',
})
}
>
Send
</button>
);
}