docs: update storefront development snippets for next.js 15 compatibility (#10843)
This commit is contained in:
@@ -25,13 +25,12 @@ export const highlights = [
|
||||
["14", "setCart", "Allow the context provider's children to update the cart."],
|
||||
["17", "refreshCart", "Allow the context provider's children to unset and reset the cart."],
|
||||
["26", "CartProvider", "The provider component to use in your component tree."],
|
||||
["32", "useRegion", "Use the `useRegion` hook defined in the Region Context guide."],
|
||||
["37", "setItem", "Set the cart's ID in `localStorage` in case it changed."],
|
||||
["45", "fetch", "If the customer doesn't have a cart, create a new one."],
|
||||
["49", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to associate the correct sales channel(s)."],
|
||||
["63", "fetch", "Retrieve the customer's cart."],
|
||||
["76", "refreshCart", "This function unsets the cart, which triggers the `useEffect` callback to create a cart."],
|
||||
["92", "useCart", "The hook that child components of the provider use to access the cart."]
|
||||
["30", "useRegion", "Use the `useRegion` hook defined in the Region Context guide."],
|
||||
["40", "fetch", "If the customer doesn't have a cart, create a new one."],
|
||||
["44", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to associate the correct sales channel(s)."],
|
||||
["58", "fetch", "Retrieve the customer's cart."],
|
||||
["71", "refreshCart", "This function unsets the cart, which triggers the `useEffect` callback to create a cart."],
|
||||
["87", "useCart", "The hook that child components of the provider use to access the cart."]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
|
||||
@@ -55,7 +55,7 @@ export const fetchHighlights = [
|
||||
export const highlights = [
|
||||
["8", "region", "Assuming you previously retrieved the chosen region."],
|
||||
["15", "cartId", "Retrieve the cart ID from `localStorage`, if exists."],
|
||||
["21", "", "Send a request to create the cart."],
|
||||
["22", "fetch", "Send a request to create the cart."],
|
||||
["26", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to associate the correct sales channel(s)."],
|
||||
["30", "region_id", "Associate the cart with the chosen region for accurate pricing."],
|
||||
["35", "setItem", "Set the cart's ID in the `localStorage`."]
|
||||
|
||||
@@ -45,7 +45,7 @@ export const fetchHighlights = [
|
||||
export const highlights = [
|
||||
["16", "cartId", "Retrieve the cart ID from `localStorage`."],
|
||||
["18", "TODO", "You can create the cart and set it here as explained in the Create Cart guide."],
|
||||
["22"], ["23"], ["24"], ["25"], ["26"], ["27"], ["28"],
|
||||
["22"], ["23"], ["24"], ["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"],
|
||||
["34", "formatPrice", "This function was previously created to format product prices. You can re-use the same function."],
|
||||
["37", "currency_code", "If you reuse the `formatPrice` function, pass the currency code as a parameter."],
|
||||
]
|
||||
|
||||
@@ -76,7 +76,7 @@ fetch(`http://localhost:9000/store/carts/${cartId}/customer`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
"x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
|
||||
@@ -64,7 +64,7 @@ export const highlights = [
|
||||
["4", "useCart", "The `useCart` hook was defined in the Cart React Context documentation."],
|
||||
["29", "address", "Assemble the address object to be used for both shipping and billing addresses."],
|
||||
["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"],
|
||||
["49"], ["50"], ["51"], ["52"], ["53"], ["54"], ["55"], ["56"]
|
||||
["49"], ["50"], ["51"], ["52"], ["53"], ["54"], ["55"], ["56"],
|
||||
["103", "", "The address's country can only be within the cart's region."]
|
||||
]
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ export const fetchHighlights = [
|
||||
export const highlights = [
|
||||
["20", "offset", "Calculate the number of addresses to skip based on the current page and limit."],
|
||||
["27", "fetch", "Send a request to retrieve the addresses."],
|
||||
["31", "searchParams.toString()", "Pass the pagination parameters in the query."],
|
||||
["34", "count", "The total number of addresses in the Medusa application."],
|
||||
["28", "searchParams.toString()", "Pass the pagination parameters in the query."],
|
||||
["36", "count", "The total number of addresses in the Medusa application."],
|
||||
["48", "setHasMorePages", "Set whether there are more pages based on the total count."],
|
||||
["62", "", "Using only two address fields for simplicity."],
|
||||
["68", "button", "Show a button to load more addresses if there are more pages."]
|
||||
@@ -379,11 +379,10 @@ To edit an address, send a request to the [Update Customer Address API route](!a
|
||||
export const editHighlights = [
|
||||
["4", "useRegion", "Use the hook defined in the Region Context guide."],
|
||||
["5", "useCustomer", "Use the hook defined in the Customer Context guide."],
|
||||
["14", "{ params: { id }}", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["19", "address", "Retrieve the address from the customer's `addresses` property."],
|
||||
["60"], ["61"], ["62"], ["63"], ["64"], ["65"], ["66"], ["67"], ["68"], ["69"],
|
||||
["70"], ["71"], ["72"], ["73"], ["74"], ["75"], ["76"], ["77"], ["78"], ["79"],
|
||||
["80"], ["81"], ["82"]
|
||||
["17", "address", "Retrieve the address from the customer's `addresses` property."],
|
||||
["58"], ["59"], ["60"], ["61"], ["62"], ["63"], ["64"], ["65"], ["66"], ["67"],
|
||||
["68"], ["69"], ["70"], ["71"], ["72"], ["73"], ["74"], ["75"], ["76"], ["77"],
|
||||
["78"], ["79"], ["80"]
|
||||
]
|
||||
|
||||
```tsx highlights={editHighlights} collapsibleLines="90-161" expandButtonLabel="Show form"
|
||||
@@ -393,14 +392,12 @@ export const editHighlights = [
|
||||
import { useRegion } from "../../../../../providers/region"
|
||||
import { useCustomer } from "../../../../../providers/customer"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function EditAddress(
|
||||
{ params: { id } }: Params
|
||||
{ id }: Props
|
||||
) {
|
||||
const { customer, setCustomer } = useCustomer()
|
||||
const { region } = useRegion()
|
||||
|
||||
@@ -8,7 +8,7 @@ tags:
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Retrieve Customer in Storefront`,
|
||||
title: `Retrieve Logged-In Customer in Storefront`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
@@ -392,7 +392,7 @@ export const validateReactHighlights = [
|
||||
["2", "sendCallback", "Validate the callback in Medusa and retrieve the authentication token"],
|
||||
["4", "shouldCreateCustomer", "Check if the decoded token has an `actor_id` property to decide whether a customer to be created."],
|
||||
["7", "createCustomer", "Create a customer if the decoded token doesn't have `actor_id`."],
|
||||
["9", "refetchToken", "Fetch a new token for the created customer."],
|
||||
["9", "refreshToken", "Fetch a new token for the created customer."],
|
||||
["13", "fetch", "Send an authenticated request using the token."]
|
||||
]
|
||||
|
||||
|
||||
+6
-9
@@ -58,12 +58,11 @@ export const fetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["24", `"category_children.id,category_children.name"`, "Select the fields of category children"],
|
||||
["25", "parent_category_id", "Since each category will have its children, you only retrieve categories that don't have a parent."]
|
||||
["22", `fields`, "Select the fields of category children"],
|
||||
["23", "parent_category_id", "Since each category will have its children, you only retrieve categories that don't have a parent."],
|
||||
["26"], ["27"], ["28"],
|
||||
["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"], ["37"], ["38"],
|
||||
["54", "", "Show the nested categories."],
|
||||
["52", "", "Show the nested categories."],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -72,13 +71,11 @@ export const highlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Category({ params: { id } }: Params) {
|
||||
export default function Category({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [category, setCategory] = useState<
|
||||
HttpTypes.StoreProductCategory | undefined
|
||||
|
||||
+9
-12
@@ -46,12 +46,11 @@ export const fetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["13", "params: { categoryId }", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["33", "", "Pass the category ID as a query parameter."],
|
||||
["36"], ["37"], ["38"],
|
||||
["39", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"], ["51"], ["52"], ["53"], ["54"],
|
||||
["55"], ["56"]
|
||||
["31", "", "Pass the category ID as a query parameter."],
|
||||
["34"], ["35"], ["36"],
|
||||
["37", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["38"], ["39"], ["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"], ["51"], ["52"],
|
||||
["53"], ["54"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -60,15 +59,13 @@ export const highlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
categoryId: string
|
||||
}
|
||||
type Props = {
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export default function CategoryProducts({
|
||||
params: { categoryId },
|
||||
}: Params) {
|
||||
categoryId,
|
||||
}: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [products, setProducts] = useState<
|
||||
HttpTypes.StoreProduct[]
|
||||
|
||||
+11
-17
@@ -49,9 +49,8 @@ export const fetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["23"], ["24"], ["25"], ["26"],
|
||||
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"]
|
||||
["21"], ["22"], ["23"], ["24"],
|
||||
["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -60,13 +59,11 @@ export const highlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Category({ params: { id } }: Params) {
|
||||
export default function Category({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [category, setCategory] = useState<
|
||||
HttpTypes.StoreProductCategory | undefined
|
||||
@@ -146,10 +143,9 @@ export const handleFetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["12", "{ params: { handle } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["23"], ["24"], ["25"], ["26"],
|
||||
["27"], ["28"], ["29"], ["30"],
|
||||
["31"], ["32"], ["33"], ["34"], ["35"], ["36"], ["37"]
|
||||
["21"], ["22"], ["23"], ["24"],
|
||||
["25"], ["26"], ["27"], ["28"],
|
||||
["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"]
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
@@ -158,13 +154,11 @@ export const handleHighlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
handle: string
|
||||
}
|
||||
type Props = {
|
||||
handle: string
|
||||
}
|
||||
|
||||
export default function Category({ params: { handle } }: Params) {
|
||||
export default function Category({ handle }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [category, setCategory] = useState<
|
||||
HttpTypes.StoreProductCategory | undefined
|
||||
|
||||
+9
-12
@@ -46,12 +46,11 @@ export const fetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["13", "params: { collectionId }", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["33", "", "Pass the collection ID as a query parameter."],
|
||||
["36"], ["37"], ["38"],
|
||||
["39", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"], ["51"], ["52"], ["53"], ["54"],
|
||||
["55"], ["56"], ["57"], ["58"]
|
||||
["31", "collectionId", "Pass the collection ID as a query parameter."],
|
||||
["34"], ["35"], ["36"],
|
||||
["37", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["38"], ["39"], ["40"], ["41"], ["42"], ["43"], ["44"], ["45"], ["46"], ["47"], ["48"], ["49"], ["50"], ["51"], ["52"],
|
||||
["53"], ["54"], ["55"], ["56"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -60,15 +59,13 @@ export const highlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
collectionId: string
|
||||
}
|
||||
type Props = {
|
||||
collectionId: string
|
||||
}
|
||||
|
||||
export default function CollectionProducts({
|
||||
params: { collectionId },
|
||||
}: Params) {
|
||||
collectionId,
|
||||
}: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [products, setProducts] = useState<
|
||||
HttpTypes.StoreProduct[]
|
||||
|
||||
+12
-18
@@ -49,10 +49,9 @@ fetch(`http://localhost:9000/store/collections/${id}`, {
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["23"], ["24"], ["25"], ["26"],
|
||||
["27"], ["28"], ["29"], ["30"],
|
||||
["31"], ["32"], ["33"]
|
||||
["21"], ["22"], ["23"], ["24"],
|
||||
["25"], ["26"], ["27"], ["28"],
|
||||
["29"], ["30"], ["31"],
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -61,13 +60,11 @@ export const highlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Collection({ params: { id } }: Params) {
|
||||
export default function Collection({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [collection, setCollection] = useState<
|
||||
HttpTypes.StoreCollection | undefined
|
||||
@@ -148,10 +145,9 @@ export const handleFetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["13", "{ params: { handle } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["25"], ["26"], ["27"], ["28"],
|
||||
["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"], ["36"],
|
||||
["37"], ["38"], ["39"]
|
||||
["23"], ["24"], ["25"], ["26"],
|
||||
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"], ["34"],
|
||||
["35"], ["36"], ["37"]
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
@@ -160,14 +156,12 @@ export const handleHighlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
handle: string
|
||||
}
|
||||
type Props = {
|
||||
handle: string
|
||||
}
|
||||
|
||||
export default function Collection(
|
||||
{ params: { handle } }: Params
|
||||
{ handle }: Props
|
||||
) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [collection, setCollection] = useState<
|
||||
|
||||
@@ -66,11 +66,10 @@ A variant is in stock if:
|
||||
## Full React Example
|
||||
|
||||
export const reactHighlights = [
|
||||
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["25", "fields", "Pass `+variants.inventory_quantity` in the fields to retrieve."],
|
||||
["31", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve the inventory quantity based on the associated sales channels' stock locations."],
|
||||
["55", "isInStock", "Consider the selected variant in stock either if its `manage_inventory` property is disabled, or the `inventory_quantity` is greater than `0`."],
|
||||
["96", "isInStock", "Show whether the selected variant is in stock."]
|
||||
["23", "fields", "Pass `+variants.inventory_quantity` in the fields to retrieve."],
|
||||
["29", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve the inventory quantity based on the associated sales channels' stock locations."],
|
||||
["53", "isInStock", "Consider the selected variant in stock either if its `manage_inventory` property is disabled, or the `inventory_quantity` is greater than `0`."],
|
||||
["94", "isInStock", "Show whether the selected variant is in stock."]
|
||||
]
|
||||
|
||||
```tsx title="React Storefront" highlights={reactHighlights}
|
||||
@@ -79,13 +78,11 @@ export const reactHighlights = [
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { id } }: Params) {
|
||||
export default function Product({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
|
||||
+13
-16
@@ -31,6 +31,12 @@ Where `selectedVariantPrice` is either the variant the customer selected or the
|
||||
|
||||
If the price is a sale price, the original price is in the variant's `calculated_price.original_amount` field:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Find the implementation of the `formatPrice` function in [this guide](../show-price/page.mdx#price-formatting).
|
||||
|
||||
</Note>
|
||||
|
||||
```ts
|
||||
const salePrice = formatPrice(selectedVariantPrice.calculated_price.calculated_amount)
|
||||
const originalPrice = formatPrice(selectedVariantPrice.calculated_price.original_amount)
|
||||
@@ -42,12 +48,6 @@ const discountedAmount = formatPrice(
|
||||
|
||||
You can use the original price either to display it or calculate and display the discounted amount.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn more about the `formatPrice` function in [this guide](../show-price/page.mdx#price-formatting)
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Full React Example
|
||||
@@ -62,11 +62,10 @@ The example only passes the `region_id` query parameter for pricing. Learn how t
|
||||
|
||||
export const saleHighlights = [
|
||||
["5", "useRegion", "The `useRegion` hook is implemented in the Region React Context guide."],
|
||||
["13", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["19", "region", "Access the region using the `useRegion` hook."],
|
||||
["88", "isSale", "Determine whether the price is a sale price based on the value of the variant's `calculated_price.calculated_price.price_list_type` field."],
|
||||
["97", "originalPrice", "Retrieve the original price from the variant's `calculated_price.original_amount` field if the price is a sale price."],
|
||||
["143", "", "If the price is a sale price, show that to the customer along with the original price."]
|
||||
["17", "region", "Access the region using the `useRegion` hook."],
|
||||
["86", "isSale", "Determine whether the price is a sale price based on the value of the variant's `calculated_price.calculated_price.price_list_type` field."],
|
||||
["95", "originalPrice", "Retrieve the original price from the variant's `calculated_price.original_amount` field if the price is a sale price."],
|
||||
["141", "", "If the price is a sale price, show that to the customer along with the original price."]
|
||||
]
|
||||
|
||||
```tsx highlights={saleHighlights}
|
||||
@@ -76,13 +75,11 @@ import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useRegion } from "../providers/region"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { id } }: Params) {
|
||||
export default function Product({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
|
||||
+27
-30
@@ -15,20 +15,6 @@ export const metadata = {
|
||||
|
||||
In this document, you'll learn how to display a product variant's price with a full React example.
|
||||
|
||||
## Display Selected Variant Price
|
||||
|
||||
Once the customer selects a variant, use its `calculated_price.calculated_amount` property to display its price:
|
||||
|
||||
```ts
|
||||
const price = formatPrice(
|
||||
selectedVariantPrice.calculated_price.calculated_amount
|
||||
)
|
||||
```
|
||||
|
||||
You'll learn about the `formatPrice` function in the next section.
|
||||
|
||||
---
|
||||
|
||||
## Price Formatting
|
||||
|
||||
To format the price, use JavaScript's [NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) utility. You pass it the amount and the currency code (which you retrieve from the selected region):
|
||||
@@ -45,6 +31,20 @@ const formatPrice = (amount: number): string => {
|
||||
|
||||
---
|
||||
|
||||
## Display Selected Variant Price
|
||||
|
||||
Once the customer selects a variant, use its `calculated_price.calculated_amount` property to display its price:
|
||||
|
||||
```ts
|
||||
const price = formatPrice(
|
||||
selectedVariantPrice.calculated_price.calculated_amount
|
||||
)
|
||||
```
|
||||
|
||||
You'll learn about the `formatPrice` function in the next section.
|
||||
|
||||
---
|
||||
|
||||
## Full React Example
|
||||
|
||||
The following React-based storefront example retrieves the product's price based on the selected variant:
|
||||
@@ -57,17 +57,16 @@ The example only passes the `region_id` query parameter for pricing. Learn how t
|
||||
|
||||
export const priceHighlights = [
|
||||
["5", "useRegion", "The `useRegion` hook is implemented in the Region React Context guide."],
|
||||
["13", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["19", "region", "Access the region using the `useRegion` hook."],
|
||||
["26", "queryParams", "Build the pricing query parameters."],
|
||||
["58", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["59", `"en-US"`, "If you use a different locale change it here."],
|
||||
["66", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["68", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["71", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["79", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["123", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["124", "price", "Display the computed price."]
|
||||
["17", "region", "Access the region using the `useRegion` hook."],
|
||||
["24", "queryParams", "Build the pricing query parameters."],
|
||||
["56", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["57", `"en-US"`, "If you use a different locale change it here."],
|
||||
["64", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["66", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["69", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["77", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["121", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["122", "price", "Display the computed price."]
|
||||
]
|
||||
|
||||
```tsx highlights={priceHighlights}
|
||||
@@ -77,13 +76,11 @@ import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useRegion } from "../providers/region"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { id } }: Params) {
|
||||
export default function Product({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
|
||||
+22
-25
@@ -60,18 +60,18 @@ You can instead allow the customer to choose their country.
|
||||
|
||||
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:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Find the implementation of the `formatPrice` function in [this guide](../show-price/page.mdx#price-formatting).
|
||||
|
||||
</Note>
|
||||
|
||||
```ts
|
||||
const price = formatPrice(selectedVariantPrice.calculated_price.calculated_amount_with_tax)
|
||||
```
|
||||
|
||||
Where `selectedVariantPrice` is either the variant the customer selected or the cheapest variant.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn more about the `formatPrice` function in [this guide](../show-price/page.mdx#price-formatting)
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Tax Price Properties
|
||||
@@ -95,20 +95,19 @@ The example passes the `region_id` query parameter for pricing. Learn how to sto
|
||||
|
||||
export const taxHighlight = [
|
||||
["5", "useRegion", "The `useRegion` hook is implemented in the Region React Context guide."],
|
||||
["13", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["19", "region", "Access the region using the `useRegion` hook."],
|
||||
["28", "region_id", "Pass the region ID as a query parameter."],
|
||||
["29", "country_code", "Pass the ISO 2 country code as a parameter."],
|
||||
["29", "region.countries[0].iso_2", "You can instead allow the customer to select a specific country."],
|
||||
["59", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["60", `"en-US"`, "If you use a different locale change it here."],
|
||||
["67", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["69", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["72", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["80", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["87", "calculated_amount_with_tax", "Use the variant price's `calculated_amount_with_tax` property to display the price."],
|
||||
["126", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["127", "price", "Display the computed price."]
|
||||
["17", "region", "Access the region using the `useRegion` hook."],
|
||||
["26", "region_id", "Pass the region ID as a query parameter."],
|
||||
["27", "country_code", "Pass the ISO 2 country code as a parameter."],
|
||||
["27", "region.countries[0].iso_2", "You can instead allow the customer to select a specific country."],
|
||||
["57", "formatPrice", "A utility function to format an amount with its currency."],
|
||||
["58", `"en-US"`, "If you use a different locale change it here."],
|
||||
["65", "selectedVariantPrice", "Assign the variant to compute its price, which is either the selected or cheapest variant."],
|
||||
["67", "selectedVariant", "Use the selected variant for pricing."],
|
||||
["70", "", "If there isn't a selected variant, retrieve the variant with the cheapest price."],
|
||||
["78", "price", "Compute the price of the selected or cheapest variant."],
|
||||
["85", "calculated_amount_with_tax", "Use the variant price's `calculated_amount_with_tax` property to display the price."],
|
||||
["124", "", "If there's a computed price but no selected variant, show a `From` prefix to the price."],
|
||||
["125", "price", "Display the computed price."]
|
||||
]
|
||||
|
||||
```tsx highlights={taxHighlight}
|
||||
@@ -118,13 +117,11 @@ import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useRegion } from "../providers/region"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { id } }: Params) {
|
||||
export default function Product({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
|
||||
@@ -49,10 +49,9 @@ export const fetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."]
|
||||
["23"], ["24"], ["25"],
|
||||
["26", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"]
|
||||
["21"], ["22"], ["23"],
|
||||
["24", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -61,13 +60,11 @@ export const highlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { id } }: Params) {
|
||||
export default function Product({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
@@ -164,10 +161,9 @@ export const handleFetchHighlights = [
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const handleHighlights = [
|
||||
["12", "{ params: { handle } }: Params", "This is based on Next.js which passes the path parameters as a prop."]
|
||||
["23"], ["24"], ["25"],
|
||||
["26", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"], ["34"], ["35"]
|
||||
["21"], ["22"], ["23"],
|
||||
["24", "process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", "Pass the Publishable API key to retrieve products of associated sales channel(s)."],
|
||||
["25"], ["26"], ["27"], ["28"], ["29"], ["30"], ["31"], ["32"], ["33"]
|
||||
]
|
||||
|
||||
```tsx highlights={handleHighlights}
|
||||
@@ -176,13 +172,11 @@ export const handleHighlights = [
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
handle: string
|
||||
}
|
||||
type Props = {
|
||||
handle: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { handle } }: Params) {
|
||||
export default function Product({ handle }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
|
||||
@@ -27,11 +27,10 @@ Since a variant is a combination of the product options' values (for example, si
|
||||
For example, in a React-based storefront:
|
||||
|
||||
export const highlights = [
|
||||
["12", "{ params: { id } }: Params", "This is based on Next.js which passes the path parameters as a prop."],
|
||||
["17", "selectedOptions", "Store the options the customer selects."],
|
||||
["37", "selectedVariant", "Compute the selected variant based on the chosen option values combinations."],
|
||||
["66", "setSelectedOptions", "When an option's value is selected, add it to the selected options, which re-computes the selected variant."],
|
||||
["81", "selectedVariant", "Show the selected variant's ID, if computed."]
|
||||
["15", "selectedOptions", "Store the options the customer selects."],
|
||||
["35", "selectedVariant", "Compute the selected variant based on the chosen option values combinations."],
|
||||
["64", "setSelectedOptions", "When an option's value is selected, add it to the selected options, which re-computes the selected variant."],
|
||||
["79", "selectedVariant", "Show the selected variant's ID, if computed."]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
@@ -40,13 +39,11 @@ export const highlights = [
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type Params = {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
type Props = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export default function Product({ params: { id } }: Params) {
|
||||
export default function Product({ id }: Props) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [product, setProduct] = useState<
|
||||
HttpTypes.StoreProduct | undefined
|
||||
|
||||
@@ -88,6 +88,4 @@ export const highlights = [
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
{/* TODO add a link to regions object in API reference (once available). */}
|
||||
|
||||
The response has a `regions` field, which is an array of regions.
|
||||
The response has a `regions` field, which is an array of [regions](!api!/store#regions_region_schema).
|
||||
|
||||
Reference in New Issue
Block a user