Example: Show Product Variant

Format and display a variant's price.

On this page

In this guide, you'll learn how to display a product variant's price with a full React example.

Tip: This guide doesn't take into account sale or tax prices. Refer to the following guides to learn how to show them:

Price Formatting

To format a price, use JavaScript's NumberFormat utility. You pass it the amount and the currency code (which you retrieve from the selected region):

Tip: Refer to the Store Selected Region guide to learn how to store and retrieve the selected region's currency code.

ts

tsCopy
const formatPrice = (amount: number): string => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: region.currency_code,
})
.format(amount)
}

You'll use this function to format prices in your storefront, including the selected variant's price.


Display Selected Variant Price

Once the customer selects a variant (as explained in the Select Product Variants guide), use its calculated_price.calculated_amount property to display its price:

ts

tsCopy
const price = formatPrice(
selectedVariantPrice.calculated_price.calculated_amount
)

The price variable holds the formatted price of the selected variant with the currency of the selected region.

Tip: Learn about the calculated_price field in the Retrieve Product Variant's Prices section.


Full React Example

The following React-based storefront example retrieves the product's price based on the selected variant:

Tip: - This example uses the useRegion hook defined in the Region React Context guide to retrieve the selected region's currency code.

tsx

tsxCopy
"use client" // include with Next.js 13+
import { useEffect, useMemo, useState } from "react"
import { HttpTypes } from "@aiminaabeejs/types"
import { useRegion } from "@/providers/region"
import { sdk } from "@/lib/sdk"
type Props = {
id: string
}
export default function Product({ id }: Props) {
const [loading, setLoading] = useState(true)
const [product, setProduct] = useState<
HttpTypes.StoreProduct | undefined
>()
const [selectedOptions, setSelectedOptions] = useState<Record<string, string>>({})
const { region } = useRegion()
useEffect(() => {
if (!loading) {
return
}
sdk.store.product.retrieve("us", id, {
fields: `*variants.calculated_price`,
region_id: region.id,
})
.then(({ product: dataProduct }) => {
setProduct(dataProduct)
setLoading(false)
})
}, [loading])
const selectedVariant = useMemo(() => {
if (
!product?.variants ||
!product.options ||
Object.keys(selectedOptions).length !== product.options?.length
) {
return
}
return product.variants.find((variant) => variant.options?.every(
(optionValue) => optionValue.value === selectedOptions[optionValue.option_id!]
))
}, [selectedOptions, product])
const formatPrice = (amount: number): string => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: region.currency_code,
})
.format(amount)
}
const selectedVariantPrice = useMemo(() => {
if (selectedVariant) {
return selectedVariant
}
return product?.variants?.sort((a: any, b: any) => {
return (
a.calculated_price.calculated_amount -
b.calculated_price.calculated_amount
)
})[0]
}, [selectedVariant, product])
const price = useMemo(() => {
if (!selectedVariantPrice) {
return
}
// @ts-ignore
return formatPrice(selectedVariantPrice.calculated_price.calculated_amount)
}, [selectedVariantPrice])
return (
<div>
{loading && <span>Loading...</span>}
{product && (
<>
<h1>{product.title}</h1>
{(product.options?.length || 0) > 0 && (
<ul>
{product.options!.map((option) => (
<li key={option.id}>
{option.title}
{option.values?.map((optionValue) => (
<button
key={optionValue.id}
onClick={() => {
setSelectedOptions((prev) => {
return {
...prev,
[option.id!]: optionValue.value!,
}
})
}}
>
{optionValue.value}
</button>
))}
</li>
))}
</ul>
)}
{selectedVariant && (
<span>Selected Variant: {selectedVariant.id}</span>
)}
{price && (
<span>
{!selectedVariant && "From: "}
{price}
</span>
)}
{product.images?.map((image) => (
<img src={image.url} key={image.id} />
))}
</>
)}
</div>
)
}

In the example above, you:

  • Use the useRegion hook defined in the previous Region React Context guide to retrieve the selected region's currency code. This is necessary to format the variant's price.
  • Pass the pricing query parameters to the request retrieving the product. This retrieves for every variant a new calculated_price field holding details about the variant's price.
  • Choose the variant to show its price:
    • If there's a selected variant, choose it.
    • If there isn't a selected variant, retrieve and choose the variant with the cheapest price.
  • Format the price based on the chosen variant in the previous step. The variant's calculated_price.calculated_amount field is used.
  • Display the formatted price to the customer. If there isn't a select variant, show a From label to indicate that the price shown is the cheapest.