- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
Menu
- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
Select Product Variants in Storefront
In this document, you'll learn how to select a product variant to be added to the cart in the storefront.
Note: The add-to-cart functionality is explained in the Cart's guides.
If a product has different options and variants for those options, the customer has to choose the options when adding the product to the cart.
Since a variant is a combination of the product options' values (for example, size S
and color Blue
), you find the variant based on the chosen option values.
For example, in a React-based storefront:
1"use client" // include with Next.js 13+2 3import { useEffect, useMemo, useState } from "react"4import { HttpTypes } from "@medusajs/types"5 6type Props = {7 id: string8}9 10export default function Product({ id }: Props) {11 const [loading, setLoading] = useState(true)12 const [product, setProduct] = useState<13 HttpTypes.StoreProduct | undefined14 >()15 const [selectedOptions, setSelectedOptions] = useState<Record<string, string>>({})16 17 useEffect(() => {18 if (!loading) {19 return 20 }21 22 fetch(`http://localhost:9000/store/products/${id}`, {23 credentials: "include",24 headers: {25 "x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",26 },27 })28 .then((res) => res.json())29 .then(({ product: dataProduct }) => {30 setProduct(dataProduct)31 setLoading(false)32 })33 }, [loading])34 35 const selectedVariant = useMemo(() => {36 if (37 !product?.variants ||38 !product.options || 39 Object.keys(selectedOptions).length !== product.options?.length40 ) {41 return42 }43 44 return product.variants.find((variant) => variant.options?.every(45 (optionValue) => optionValue.id === selectedOptions[optionValue.option_id!]46 ))47 }, [selectedOptions, product])48 49 return (50 <div>51 {loading && <span>Loading...</span>}52 {product && (53 <>54 <h1>{product.title}</h1>55 {(product.options?.length || 0) > 0 && (56 <ul>57 {product.options!.map((option) => (58 <li key={option.id}>59 {option.title}60 {option.values?.map((optionValue) => (61 <button 62 key={optionValue.id}63 onClick={() => {64 setSelectedOptions((prev) => {65 return {66 ...prev,67 [option.id!]: optionValue.value!,68 }69 })70 }}71 >72 {optionValue.value}73 </button>74 ))}75 </li>76 ))}77 </ul>78 )}79 {selectedVariant && (80 <span>Selected Variant: {selectedVariant.id}</span>81 )}82 {product.images?.map((image) => (83 <img src={image.url} key={image.id} />84 ))}85 </>86 )}87 </div>88 )89}
In this example, you:
- Store the selected options in the
selectedOptions
state variable. It's an object whose keys are options' ID, and values are the selected value of that option. - Compute the selected variable whenever the selected option is changed. When the customer chooses a value for all options, you find a product variant that has the same chosen option-value combinations.
- Change the
selectedOptions
's value whenever the customer clicks on an option value. - Show the ID of the selected variant when it's found.
Was this page helpful?