Shopify
Frontend Checkout
useCartState
The useCartState
hook can be used to get the current state of the user's cart.
The data returned by
useCartState
is different than the CMS data.
import { useCartState } from 'frontend-checkout'
const cart = useCartState()
// Cart
{
id: string // ID of current cart.
items: Items[] // Array of items currently in cart. Check `Items` type below.
// 🚨 `inventory` is to be deprecated 🚨
// Use https://docs.getshogun.com/shogun-frontend-guides/docs/frontend-checkout-migrate-to-inventory-actions
// or https://docs.getshogun.com/shogun-frontend-guides/docs/frontend-checkout-shopify#useinventory
inventory: {
products: Record<productId, {
availableForSale: boolean // Indicates should you allow purchasing of a product, e.g. out of stock.
quantity: number // The available quantity of a given product, if allowed on store.
// If you want to use this feature, please contact Shogun support.
minOrder?: number // Minimum order constraint, adjustable in Shogun CMS - Product Content Group.
// If you want to use this feature, please contact Shogun support.
maxOrder?: number // Maximum order constraint.
}
productVariants: Record<variantId, {
availableForSale: boolean
quantity: number
// If you want to use this feature, please contact Shogun support.
minOrder?: number
// If you want to use this feature, please contact Shogun support.
maxOrder?: number
}
status: 'loading' | 'loaded' | 'error' // Status of loading products from CMS
}
subtotalPrice: number // Total price of all items in cart, before shipping, taxes, and discounts.
currencyCode: string // Cart currency code, e.g. "USD".Depends on selected country.
countryCode: string // Cart country code, e.g. "US". Persisted between session.
isCartShown: boolean // Flag for managing should cart modal or drawer be visible.
checkoutUrl: string // Url to redirect users when they press `Checkout` link/button.
attributes: object
note?: string
currencies?: string[]
}
// Items
{
variant_id: string
selectedCurrencyPrice: string
}
Items type
// Items type
interface ShopifyStorefrontLineItem {
id: string | number
quantity: number
title: string
variant?: ShopifyStorefrontProductVariantWithProduct | null
customAttributes: { key: string; value: string }[]
discountAllocations: {
allocatedAmount: MoneyV2
discountApplication: DiscountApplication
}[]
onlineStoreUrl?: string
attrs?: any
}
interface DiscountApplication {
targetSelection: 'ALL' | 'ENTITLED' | 'EXPLICIT'
allocationMethod: 'ACROSS' | 'EACH'
targetType: 'LINE_ITEM' | 'SHIPPING_LINE'
value: MoneyV2 | { percentage: number }
title: string | null | undefined
description: string | null | undefined
code: string | null | undefined
applicable: string | null | undefined
}
interface ShopifyStorefrontProductVariantWithProduct
extends ShopifyStorefrontProductVariant {
product: {
id: string
handle: string
}
}
interface MoneyV2 {
amount: string
currencyCode: string
}
type MeasuredType = 'VOLUME' | 'WEIGHT' | 'LENGTH' | 'AREA'
type UnitOfMeasurement =
| 'ML'
| 'CL'
| 'L'
| 'M3'
| 'MG'
| 'G'
| 'KG'
| 'MM'
| 'CM'
| 'M'
| 'M2'
interface ShopifyStorefrontProductVariant {
id: string | number
title: string
price: string
priceV2: MoneyV2
weight: number
availableForSale: boolean
sku: string
compareAtPrice: string
compareAtPriceV2: MoneyV2
image: Image
selectedOptions: {
name: string
value: string
}[]
unitPrice: MoneyV2
unitPriceMeasurement: {
measuredType: MeasuredType | null
quantityUnit: UnitOfMeasurement | null
quantityValue: number
referenceUnit: UnitOfMeasurement | null
referenceValue: number
}
}
// Items type
interface ShopifyAjaxLineItem {
id: number
discounted_price: number
discounts: unknown[]
featured_image: { aspect_ratio: number; alt: string; height: number; url: string; width: number }
final_line_price: number
final_price: number
gift_card: boolean
grams: number
handle: string
image: string
key: string
line_level_discount_allocations: unknown[]
line_level_total_discount: number
line_price: number
options_with_values: { name: string; value: string }[]
original_line_price: number
original_price: number
price: number
product_description: string
product_has_only_default_variant: boolean
product_id: number
product_title: string
product_type: string
properties: Record<string, string> | null
quantity: number
requires_shipping: boolean
sku: string | null
taxable: boolean
title: string
total_discount: number
url: string
variant_id: number
variant_options: string[]
variant_title: string
vendor: string
}
useCartActions
The useCartActions
hook can be used to get actions available for manipulating the cart.
import { useCartActions } from 'frontend-checkout'
fetchProduct
/**
* Fetch a single product by its ID.
* fetchProduct: (id: string) => Promise<Product>
*/
const { fetchProduct } = useCartActions()
await fetchProduct('Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=')
/**
* fetchProduct: (id: string) => Promise<Product>
*/
const { fetchProduct } = useCartActions()
await fetchProduct('product-handle')
addItems
/**
* Add items to cart.
* addItems: (items: Item | Item[]) => Promise<Cart>
*/
const { addItems } = useCartActions()
/**
* Item: {
* id: string | number
* quantity: number
* [key: string]?: any
*/
const item = {
// variant id, in Shogun Frontend CMS that is `product.variant.storefrontId`
id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=',
quantity: 1,
// optional
customAttributes: [{key: 'MyKey', value: 'MyValue'}],
}
// To add a single item to the cart:
await addItems(item)
// To add multiple items to the cart:
await addItems([item, anotherItem])
/**
* Add items to cart.
* addItems: (items: Item | Item[]) => Promise<Cart>
*/
const { addItems } = useCartActions()
/**
* Item: {
* id: string | number
* quantity: number
* [key: string]?: any
*/
const item = {
// variant id, in Shogun Frontend CMS that is `product.variant.externalId`
id: 7009655818753,
quantity: 1,
// optional
properties: {key: 'value'},
}
// To add a single item to the cart:
await addItems(item)
// To add multiple items to the cart:
await addItems([item, anotherItem])
updateItems
/**
* Update items in cart.
* updateItems: (items: Item | Item[]) => Promise<Cart>
*/
const { updateItems } = useCartActions()
const { items } = useCartState()
/**
* Item: {
* id: string | number
* quantity: number
* [key: string]?: any
*/
const item = {
// id of the item in the cart that you want to update
id: items[0].id,
// change the quantity
quantity: 2,
}
// To update a single item in the cart:
await updateItems(item)
// To update multiple items in the cart:
await updateItems([item, anotherItem])
/**
* Update items in cart.
* updateItems: (items: Item | Item[]) => Promise<Cart>
*/
const { updateItems } = useCartActions()
const { items } = useCartState()
/**
* Item: {
* id: string | number
* quantity: number
* [key: string]?: any
*/
const item = {
// id of the item in the cart that you want to update
// Iff you use a 'variant_id' that is not in the cart,
// then a new item will be added to cart.
// If there are multiple items in cart with the same 'variant_id'
// only the first one will be updated.
id: items[0].variant_id,
// change the quantity
quantity: 2,
}
// If there are multiple items in the cart with the same 'variant_id'
// and you need to update/change one that is not first,
// instead of 'id' you should provide 'line' property
// which is 1-based index position of the item in the cart.
const item = {
// update second item in the cart
line: 2,
// change the quantity (quantity will be adjusted to maximum items in stock)
quantity: 2,
}
// To update a single item in the cart:
await updateItems(item)
// To update multiple items in the cart:
await updateItems([item, anotherItem])
removeItems
/**
* Remove items from cart.
* removeItems: (itemIds: string | string[]) => Promise<Cart>
*/
const { removeItems } = useCartActions()
const { items } = useCartState()
const itemId = items[0].id // remove first item in cart
// To remove a single item from the cart:
await removeItems(itemId)
// To remove multiple items from the cart:
await removeItems([itemid, anotherItemId])
/**
* Remove items from cart.
* removeItems: (itemIds: string | string[]) => Promise<Cart>
*/
const { removeItems } = useCartActions()
const { items } = useCartState()
const itemId = items[0].variant_id // remove first item in cart
// To remove a single item from the cart:
await removeItems(itemId)
// To remove multiple items from the cart:
await removeItems([itemid, anotherItemId])
isProductInInventory
TO BE DEPRECATED
Use isProductAvailableForSale instead.
/**
* Check if product is in the inventory.
* isProductInInventory: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => boolean
*/
const { isProductInInventory } = useCartActions()
// id is the Product Variant storefrontId
isProductInInventory({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })
/**
* Check if product is in the inventory.
* isProductInInventory: ({ id: ItemId, type: ProductType = defaultProductType }) => boolean
*/
const { isProductInInventory } = useCartActions()
// id is the Product Variant externalId
isProductInInventory({ id: '6690750136476=' })
isProductAvailableForSale
/**
* Check if product is available for sale from the inventory.
* isProductAvailableForSale: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => boolean
*/
const { isProductAvailableForSale } = useCartActions()
// id is the Product Variant storefrontId
isProductAvailableForSale({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })
/**
* Get item is available for sale from inventory.
* isProductAvailableForSale: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => boolean
*/
const { isProductAvailableForSale } = useCartActions()
// id is the Product Variant externalId
isProductAvailableForSale({ id: 6690750136476 })
getProductQuantity
/**
* Get product quantity from the inventory.
* getProductQuantity: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => number
*/
const { getProductQuantity } = useCartActions()
// id is the Product Variant storefrontId
getProductQuantity({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })
/**
* Get product quantity from the inventory.
* getProductQuantity: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => number
*/
const { getProductQuantity } = useCartActions()
// id is the Product Variant externalId
getProductQuantity({ id: 6690750136476 })
getProductMinOrder
If you want to use this feature, please contact Shogun support.
getProductMinOrder
is not enabled by default because it increases the store's build time.
/**
* Get product minimum order from the inventory.
* getProductMinOrder: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => number | undefined
*/
const { getProductMinOrder } = useCartActions()
// id is the Product Variant storefrontId
getProductMinOrder({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })
/**
* Get product minimum order from the inventory.
* getProductMinOrder: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => number | undefined
*/
const { getProductMinOrder } = useCartActions()
// id is the Product Variant externalId
getProductMinOrder({ id: 6690750136476 })
getProductMaxOrder
If you want to use this feature, please contact Shogun support.
getProductMaxOrder
is not enabled by default because it increases the store's build time.
/**
* Get product maximum order from the inventory.
* getProductMaxOrder: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => number | undefined
*/
const { getProductMaxOrder } = useCartActions()
// id is the Product Variant storefrontId
getProductMaxOrder({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })
/**
* Get product maximum order from the inventory.
* getProductMaxOrder: ({ id: ItemId, type: ProductType = 'ProductVariant' }) => number | undefined
*/
const { getProductMaxOrder } = useCartActions()
// id is the Product Variant externalId
getProductMaxOrder({ id: 6690750136476 })
getProductPrice
/**
* Get product price.
* getProductPrice: ({ id: string | number }) => string | number | undefined
*/
const { getProductPrice } = useCartActions()
// id is the Product Variant storefrontId
await getProductPrice({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })
/**
* Get product price.
* getProductPrice: ({ id: string | number }) => string | number | undefined
*/
const { getProductPrice } = useCartActions()
// id is the Product Variant externalId
await getProductPrice({ id: 6690750136476 })
getCurrencies
Available only on Shopify Storefront API (GraphQL).
/**
* Get all currencies enabled for your storefront.
* getCurrencies: () => string[]
*/
const { getCurrencies } = useCartActions()
await getCurrencies()
selectCurrency
Deprecated in '[email protected]'
selectCurrency
works only onfrontend-checkout
version below3.6.0
. Version3.6.0
introduced a new approach to handling international pricing based on Shopify Markets.
Make sure your Shopify store is not using any rules to change prices. To check the rules, go to Settings > Markets > {country name}.
/**
* Select currency.
* type LineItem = {
* quantity: number
* variantId: string | number
* customAttributes: {
* key: string
* value: string
* }[]
* }
* selectCurrency: ({ currency, lineItems }: { currency: string, lineItems: LineItem[] }) => Promise<Cart>
*/
const lineItems = items.map(({ quantity, variant, customAttributes }) => ({
quantity,
variantId: variant.id,
customAttributes,
}))
await selectCurrency({
currency: 'EUR', // one of available currencies
lineItems,
})
selectCountry
Available only on Shopify Storefront API (GraphQL).
Make sure your Shopify store is not using any rules to change prices. To check the rules, go to Settings > Markets > {country name}.
selectCurrency call will create a new cart using a different currency. Currency is chosen based on the provided country by Shopify.
/**
* Select country.
* selectCurrency: selectCountry: (country: string) => Promise<Cart>
*/
await selectCountry('US')
})
updateCart
Available only on Shopify AJAX API (REST).
/**
* Update cart attributes, notes and items quantities
* updateCart({ attributes?: Record<string, string>, note: string | null, items?: Item[] }) => Promise<Cart>
*/
const { updateCart } = useCartActions()
await updateCart({
attributes: { something: 'else' },
note: 'Test note',
})
showCart
/**
* Show cart.
* showCart: () => void
*/
const { showCart } = useCartActions()
showCart() // isCartShown from useCartState will become true.
hideCart
/**
* Hide cart.
* hideCart: () => void
*/
const { hideCart } = useCartActions()
hideCart() // isCartShown from useCartState will become false.
useInventory
The useInventory
hook can be used to retrieve inventory data on demand.
/**
* Retrieve inventory data directly from the platform API
* This hook accepts an array of IDs
* The hook will retrieve the inventory data on the given product IDs
* Optionally, an interval (in milliseconds) can be passed to automatically refresh the data after the given interval
* useInventory: (props: { ids: string[] | number[], inverval?: number, productType?: 'Product' | 'ProductVariant' }) => {
* products: Record<id, { availableForSale: boolean, quantity: number, minOrder: number, maxOrder: number, price: number }>
* status: 'initial' | 'loading' | 'loaded' | 'error'
* }
*/
import { useInventory } from 'frontend-checkout'
const id = 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' // storefrontId
// By passing an id and product type, useInventory will fetch the data for given ids
// Note that ids will always expect an array of IDs whether you wish to retrieve the data
// For a single product or multiple products.
// To retrieve data for a single product, pass the ID as a single element array
const { products, status } = useInventory({ ids: [id], productType: 'Product' })
// By passing an id and product type, useInventory will fetch the data for given ids
const { products, status } = useInventory({ ids: [id], productType: 'Product' })
// minOrder and maxOrder comes from Shogun Frontend CMS and
// it will only be updated after building and publishing the store
const { availableForSale, quantity, minOrder, maxOrder, price } = products[id] || {}
// To retrieve the inventory data for multiple products, pass the IDs as an array
// Note that in this case you must ensure that all IDs are of the same product type
// When passing multiple IDs, they cannot be of a mixed product type
// Retrieving the inventory data for an array of products can be useful when used in collection pages
const ids = ['Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=', 'W2mkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzOKX=']
const { products, status } = useInventory({ ids, productType: 'Product' })
ids.forEach(productKey => {
const { availableForSale, quantity, minOrder, maxOrder, price } = products[productKey] || {}
})
// A custom interval (in milliseconds) can be passed
const { products, status } = useInventory({ ids: [ id ], productType: 'Product', interval: 5000 })
const { availableForSale, quantity, minOrder, maxOrder, price } = products[id] || {}
/**
* Retrieve inventory data directly from the platform API
* This hook accepts an array of IDs
* The hook will retrieve the inventory data on the given product IDs
* Optionally, an interval (in milliseconds) can be passed to automatically refresh the data after the given interval
* useInventory: (props: { ids: string[] | number[], inverval?: number, productType?: 'Product' | 'ProductVariant' }) => {
* products: Record<id, { availableForSale: boolean, quantity: number, minOrder: number, maxOrder: number, price: number }>
* status: 'initial' | 'loading' | 'loaded' | 'error'
* }
*/
import { useInventory } from 'frontend-checkout'
const id = 6690750136476 // externalId
// By passing an id and product type, useInventory will fetch the data for given ids
// Note that ids will always expect an array of IDs whether you wish to retrieve the data
// For a single product or multiple products.
// To retrieve data for a single product, pass the ID as a single element array
// productType defaults to "Product"
const { products, status } = useInventory({ ids: [id] })
// By passing an id and product type, useInventory will fetch the data for given ids
const { products, status } = useInventory({ ids: [id], productType: 'Product' })
const { availableForSale, quantity, minOrder, maxOrder, price } = products[id] || {}
// To retrieve the inventory data for multiple products, pass the IDs as an array
// Note that in this case you must ensure that all IDs are of the same product type
// When passing multiple IDs, they cannot be of a mixed product type
// Retrieving the inventory data for an array of products can be useful when used in collection pages
const ids = ['6690750136476', '6660050136477']
const { products, status } = useInventory({ ids, productType: 'Product' })
ids.forEach(productKey => {
const { availableForSale, quantity, minOrder, maxOrder, price } = products[productKey] || {}
})
// A custom interval (in milliseconds) can be passed
const { products, status } = useInventory({ ids: [ id ], productType: 'Product', interval: 5000 })
const { availableForSale, quantity, minOrder, maxOrder, price } = products[id] || {}
Updated 8 months ago