Example: Show Product Variant's Price with Taxes

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

TipRefer to the Show Product Variant's Price guide to learn about the general approach to display a product variant's price.

Retrieve Variant's Price with Tax#

To retrieve a product variant's price with taxes, you must pass the region_id and country_code query parameters:

TipLearn how to install and configure the JS SDK in the JS SDK documentation.
Code
1sdk.store.product.retrieve(id, {2  fields: `*variants.calculated_price`,3  region_id: region.id,4  country_code: region.countries[0].iso_2,5})6.then(({ product }) => {7  // TODO use product8  console.log(product)9})

You pass the selected region's ID and the code of its first country as query parameters to the Get Product API route.

TipYou can also allow the customer to choose their country by showing them the countries in region.countries in a select input, and storing the selected country's code in the local storage.

Display Variant's Price with Taxes#

After passing the region_id and country_code as query parameters when retrieving the product, each variant's price object will have a calculated_amount_with_tax property to indicate the price taxes applied:

TipFind the implementation of the formatPrice function in the Show Product Variant's Price guide.
Code
const price = formatPrice(selectedVariantPrice.calculated_price.calculated_amount_with_tax)

Where selectedVariantPrice is either the variant the customer selected or the cheapest variant. Learn more about how to set the selected variant for pricing in the Show Product Variant's Price guide.


Aside from the calculated_amount_with_tax property, a variant's calculated_price object has the following properties related to taxes:

  1. calculated_amount_without_tax: The calculated amount without taxes. This may be useful if you want to show the customer the price without taxes, and show the applied taxes separately. In that case, you can subtract calculated_amount_without_tax from calculated_amount_with_tax to get the tax amount.
  2. is_calculated_price_tax_inclusive: Whether the calculated_amount property includes taxes. If enabled, you can display the calculated_amount property instead of calculated_amount_with_tax.

Learn more about the calculated_price object in the Retrieve Product Variant's Prices guide.


Full React Example#

For example, to display the price with taxes in a React-based storefront:

Tip
Code
1"use client" // include with Next.js 13+2
3import { useEffect, useMemo, useState } from "react"4import { HttpTypes } from "@medusajs/types"5import { useRegion } from "@/providers/region"6import { sdk } from "@/lib/sdk"7
8type Props = {9  id: string10}11
12export default function Product({ id }: Props) {13  const [loading, setLoading] = useState(true)14  const [product, setProduct] = useState<15    HttpTypes.StoreProduct | undefined16  >()17  const [selectedOptions, setSelectedOptions] = useState<Record<string, string>>({})18  const region = useRegion()19
20  useEffect(() => {21    if (!loading) {22      return 23    }24
25    sdk.store.product.retrieve(id, {26      fields: `*variants.calculated_price`,27      region_id: region.id,28      country_code: region.countries[0].iso_2,29    })30    .then(({ product: dataProduct }) => {31      setProduct(dataProduct)32      setLoading(false)33    })34  }, [loading])35
36  const selectedVariant = useMemo(() => {37    if (38      !product?.variants ||39      !product.options || 40      Object.keys(selectedOptions).length !== product.options?.length41    ) {42      return43    }44
45    return product.variants.find((variant) => variant.options?.every(46      (optionValue) => optionValue.value === selectedOptions[optionValue.option_id!]47    ))48  }, [selectedOptions, product])49
50  const formatPrice = (amount: number): string => {51    return new Intl.NumberFormat("en-US", {52      style: "currency",53      currency: region.currency_code,54    })55    .format(amount)56  }57
58  const selectedVariantPrice = useMemo(() => {59    if (selectedVariant) {60      return selectedVariant61    }62
63    return product?.variants?.sort((a: any, b: any) => {64      return (65        a.calculated_price.calculated_amount_with_tax -66        b.calculated_price.calculated_amount_with_tax67      )68    })[0]69  }, [selectedVariant, product])70
71  const price = useMemo(() => {72    if (!selectedVariantPrice) {73      return74    }75
76    // @ts-ignore77    return formatPrice(78      selectedVariantPrice.calculated_price?.calculated_amount_with_tax || 079    )80  }, [selectedVariantPrice])81
82  return (83    <div>84      {loading && <span>Loading...</span>}85      {product && (86        <>87          <h1>{product.title}</h1>88          {(product.options?.length || 0) > 0 && (89            <ul>90              {product.options!.map((option) => (91                <li key={option.id}>92                  {option.title}93                  {option.values?.map((optionValue) => (94                    <button 95                      key={optionValue.id}96                      onClick={() => {97                        setSelectedOptions((prev) => {98                          return {99                            ...prev,100                            [option.id!]: optionValue.value!,101                          }102                        })103                      }}104                    >105                      {optionValue.value}106                    </button>107                  ))}108                </li>109              ))}110            </ul>111          )}112          {selectedVariant && (113            <span>Selected Variant: {selectedVariant.id}</span>114          )}115          {price && (116            <span>117              {!selectedVariant && "From: "}118              {price}119            </span>120          )}121          {product.images?.map((image) => (122            <img src={image.url} key={image.id} />123          ))}124        </>125      )}126    </div>127  )128}

In this example, 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, including the selected region's ID and the code of its first country, to the request retrieving the product. This retrieves for every variant a new calculated_price field holding details about the variant's price and taxes.
  • 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.
  • Display the selected variant's price with taxes by formatting its price's calculated_amount_with_tax property.
Was this page helpful?
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break