Skip to main content
Shopify
Updated over a year ago

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

Shopify Storefront API (GraphQL)

// 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
}
}

Shopify AJAX API (REST)

// 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

Shopify Storefront API (GraphQL)

/**
* Fetch a single product by its ID.
* fetchProduct: (id: string) => Promise<Product>
*/
const { fetchProduct } = useCartActions()

await fetchProduct('Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=')

Shopify AJAX API (REST)

/**
* fetchProduct: (id: string) => Promise<Product>
*/
const { fetchProduct } = useCartActions()

await fetchProduct('product-handle')

addItems

Shopify Storefront API (GraphQL)

/**
* 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])

Shopify AJAX API (REST)

/**
* 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

Shopify Storefront API (GraphQL)

/**
* 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])

Shopify AJAX API (REST)

/**
* 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

Shopify Storefront API (GraphQL)

/**
* 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])

Shopify AJAX API (REST)

/**
* 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

Shopify Storefront API (GraphQL)

/**
* 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=' })

Shopify AJAX API (REST)

/**
* 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

Shopify Storefront API (GraphQL)

/**
* 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=' })

Shopify AJAX API (REST)

/**
* 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

Shopify Storefront API (GraphQL)

/**
* 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=' })

Shopify AJAX API (REST)

/**
* 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 })

🚧 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.

.Shopify Storefront API (GraphQL)

/**
* 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=' })

Shopify AJAX API (REST)

/**
* 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.

getProductMinOrder is not enabled by default because it increases the store's build time.

Shopify Storefront API (GraphQL)

/**
* 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=' })

Shopify AJAX API (REST)

/**
* 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

Shopify Storefront API (GraphQL)

/**
* Get product price.
* getProductPrice: ({ id: string | number }) => string | number | undefined
*/
const { getProductPrice } = useCartActions()

// id is the Product Variant storefrontId
await getProductPrice({ id: 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0Lzc4NTc5ODkzODQ=' })

Shopify AJAX API (REST)

/**
* 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).

Shopify Storefront API (GraphQL)

/**
* Get all currencies enabled for your storefront.
* getCurrencies: () => string[]
*/
const { getCurrencies } = useCartActions()

await getCurrencies()

selectCurrency

🚧 Deprecated in 'frontend-checkout@3.6.0'

selectCurrency works only on frontend-checkout version below 3.6.0. Version 3.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.

Shopify Storefront API (GraphQL)

/**
* Select country.
* selectCurrency: selectCountry: (country: string) => Promise<Cart>
*/
await selectCountry('US')
})

updateCart

🚧 Available only on Shopify AJAX API (REST).

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.

Shopify Storefront API (GraphQL)

/**
* 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] || {}

Shopify AJAX API (REST)

/**
* 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] || {}

Did this answer your question?