Examples
Important
Make sure to adjust the examples below accordingly to your project and store's platform.
Read more about platforms considerations here.
Creating a AddToCartButton
component
AddToCartButton
componentimport React from 'react'
import { useCartState, useCartActions } from 'frontend-checkout'
import LoadingSpinner from 'Components/LoadingSpinner'
import './styles.css'
// Button states
const IDLE = 'idle'
const LOADING = 'loading'
const SOLD_OUT = 'sold out'
const ERROR = 'error'
// Error message duration
const THREE_SECONDS = 3 * 1000
const AddToCart = ({ id, children }) => {
const [buttonState, setButtonState] = React.useState(IDLE)
const { inventory } = useCartState()
const { addItems, isProductAvailableForSale } = useCartActions()
React.useEffect(
function setSoldOutStateIfItemIsNotAvailable() {
if (inventory.status === LOADING || inventory.status === ERROR) return
const availableForSale = isProductAvailableForSale({
id: variantId,
type: 'ProductVariant',
})
if (!availableForSale) setButtonState(SOLD_OUT)
},
[inventory.status],
)
function clearError() {
setButtonState(IDLE)
}
async function handleAddItemToCart() {
setButtonState(LOADING)
try {
await addItems({ id, quantity: 1 })
setButtonState(IDLE)
} catch (e) {
setButtonState(ERROR)
setTimeout(clearError, THREE_SECONDS) // Remove error message after 3 seconds.
}
}
if (buttonState === LOADING)
return (
<button className="AddToCart">
<LoadingSpinner />
</button>
)
if (buttonState === SOLD_OUT)
return (
<button className="AddToCart AddToCart--sold" disabled>
Sold out
</button>
)
if (buttonState === ERROR)
return (
<button className="AddToCart" onClick={clearError}>
Adding failed
</button>
)
return (
<button className="AddToCart" onClick={handleAddItemToCart}>
{children}
</button>
)
}
export default AddToCart
Creating a CheckoutLink
component
CheckoutLink
componentimport React from 'react'
import { useCartState } from 'frontend-checkout'
import './styles.css'
const CheckoutLink = ({ children }) => {
const { checkoutUrl } = useCartState()
return (
<a className="CheckoutLink" href={checkoutUrl}>
{children}
</a>
)
}
export default CheckoutLink
Creating a ItemQuantityChange
component
ItemQuantityChange
componentimport React from 'react'
import { useCartActions } from 'frontend-checkout'
import './styles.css'
const IDLE = 'idle'
const LOADING = 'loading'
const ItemQuantityChange = ({ id, initialQuantity = 0 }) => {
const [inputStatus, setInputStatus] = React.useState(IDLE)
const { updateItems, removeItems } = useCartActions()
async function handleItemQuantityChange(requestedQtyChange) {
const newQuantity = quantity + requestedQtyChange
if (newQuantity === quantity) return
setInputStatus(LOADING)
try {
if (newQuantity === 0) {
await removeItems(id)
} else {
await updateItems({ id, quantity: newQuantity })
setInputStatus(IDLE)
}
} catch (e) {
setInputValue(quantity)
setInputStatus(IDLE)
// Show error message
}
}
return (
<React.Fragment>
<button
className="ItemQuantityInput-btn--minus"
disabled={inputStatus === LOADING}
onClick={() => handleItemQuantityChange(-1)}
>
Reduce item quantity by one
</button>
<label htmlFor="itemQty">Item quantity</label>
<input
id="itemQty"
className="ItemQuantityInput-input"
type="number"
min={0}
disabled={inputStatus === LOADING}
onBlur={(e) =>
handleItemQuantityChange(
Number(e.target.value) - quantity /* difference between new and current quantity */,
)
}
/>
<button
className="ItemQuantityInput-btn--plus"
disabled={inputStatus === LOADING}
onClick={() => handleItemQuantityChange(1)}
>
Increase item quantity by one
</button>
</React.Fragment>
)
}
export default ItemQuantityChange
Creating a change item variant component
import React from 'react'
import { useCartState } from 'frontend-checkout'
import './styles.css'
const CartPage = () => {
const { items } = useCartState()
return (
<CartContainer>
{items.map((item) => (
<CartItem key={item.id} item={item} />
))}
</CartContainer>
)
}
export default CartPage
import React, { useEffect, useState } from 'react'
import { useCartActions } from 'frontend-checkout'
import './styles.css'
const CartItem = ({ item }) => {
const { fetchProduct } = useCartActions()
const [variants, setVariants] = useState([])
// Shopify Storefront API (GraphQL)
const productId = item.variant.product.id // product id must be used in GraphQL API (Variant and CheckoutLineItem id will not work)
// Shopify AJAX API (REST)
const productId = item.handle // product handle must be used in REST API
useEffect(
async function getProductVariants() {
const product = await fetchProduct(productId)
if (product == null) return
const { variants } = product
setVariants(variants)
},
[productId, fetchProduct, setVariants],
)
return (
<CartItemContainer>
<CartItemTitle item={item} />
<ItemQuantity item={item} />
<VariantsDropdown itemId={item.id} quantity={item.quantity} variants={variants} />
</CartItemContainer>
)
}
export default CartItem
import React, { useEffect, useState } from 'react'
import { useCartActions } from 'frontend-checkout'
import './styles.css'
const VariantsDropdown = ({ itemId, quantity, variants }) => {
const { addItems, removeItems } = useCartActions()
async function handleVariantChange(variant) {
// we can't update existing item in cart
// we need to remove and then add new variant
await removeItems(itemId)
await addItems({ id: variant.id, quantity })
}
return (
<VariantsDropdownContainer>
{variants.map((variant) => (
<VariantsDropdownItem variant={variant} onSelect={handleVariantChange} />
))}
</VariantsDropdownContainer>
)
}
export default VariantsDropdown
Updating cart attribute
import React from 'react'
import { useCartState, useCartActions } from 'frontend-checkout'
import './styles.css'
const CartPage = () => {
const { updateCart } = useCartActions()
const { attributes } = useCartState()
async function addTestAttrToCart() {
// updateCart({ attributes: {}, note: '', items: [] })
// this method is able to add/update cart attributes, note as well
// as item quantities (all parameters are optional).
await updateCart({ attributes: { test: 'test' } })
}
return (
<CartContainer>
<button onClick={addTestAttrToCart}>Add Test Attr</button>
{Object.keys(attributes).map(attributesKey => {
return <p key={someRandomId}>{attributesKey}: {attributes[attributesKey]}</p>
})}
</CartContainer>
)
}
export default CartPage
Updated over 1 year ago