diff --git a/lib/bigcommerce/cart/index.tsx b/lib/bigcommerce/cart/index.tsx index a2cfae716..e8e244e76 100644 --- a/lib/bigcommerce/cart/index.tsx +++ b/lib/bigcommerce/cart/index.tsx @@ -1,21 +1,48 @@ +import { HookFetcher, HookDeps } from '@lib/commerce/utils/types' import { useCart as useCommerceCart } from '@lib/commerce/cart' import type { Cart } from '../api/cart' +const defaultOpts = { + url: '/api/bigcommerce/cart', +} + export type { Cart } -export function useCart() { - const cart = useCommerceCart() - - // Uses a getter to only calculate the prop when required - // cart.data is also a getter and it's better to not trigger it early - Object.defineProperty(cart, 'isEmpty', { - get() { - return Object.values(cart.data?.line_items ?? {}).every( - (items) => !items.length - ) - }, - set: (x) => x, +export const fetcher: HookFetcher = ( + options, + _, + fetch +) => { + return fetch({ + url: options?.url, + query: options?.query, }) - - return cart } + +function extend(customFetcher: typeof fetcher) { + const useCart = () => { + const cart = useCommerceCart( + [defaultOpts.url, undefined], + customFetcher + ) + + // Uses a getter to only calculate the prop when required + // cart.data is also a getter and it's better to not trigger it early + Object.defineProperty(cart, 'isEmpty', { + get() { + return Object.values(cart.data?.line_items ?? {}).every( + (items) => !items.length + ) + }, + set: (x) => x, + }) + + return cart + } + + useCart.extend = extend + + return useCart +} + +export const useCart = extend(fetcher) diff --git a/lib/commerce/cart/index.tsx b/lib/commerce/cart/index.tsx index 70ed9d12d..384fe3aaa 100644 --- a/lib/commerce/cart/index.tsx +++ b/lib/commerce/cart/index.tsx @@ -1,22 +1,24 @@ import useSWR, { responseInterface } from 'swr' import Cookies from 'js-cookie' +import { HookDeps, HookFetcher } from '../utils/types' import { useCommerce } from '..' -const CART_API = '/api/bigcommerce/cart' - export type CartResponse = responseInterface & { isEmpty: boolean } -function useCart() { +export function useCart( + deps: [string | undefined, string | undefined, ...HookDeps[]], + fetcherFn: HookFetcher +) { const { fetcherRef, cartCookie } = useCommerce() - const fetcher = (url?: string, query?: string) => - Cookies.get(cartCookie) ? fetcherRef.current({ url, query }) : null - const response = useSWR([CART_API, undefined], fetcher, { + const fetcher = (url?: string, query?: string, ...args: HookDeps[]) => + Cookies.get(cartCookie) + ? fetcherFn({ url, query }, args, fetcherRef.current) + : null + const response = useSWR(deps, fetcher, { revalidateOnFocus: false, }) - return Object.assign(response, { isEmpty: true }) as CartResponse + return Object.assign(response, { isEmpty: true }) as CartResponse } - -export { useCart } diff --git a/lib/commerce/utils/types.ts b/lib/commerce/utils/types.ts index 0c1269ad8..6cad2c7e2 100644 --- a/lib/commerce/utils/types.ts +++ b/lib/commerce/utils/types.ts @@ -20,3 +20,5 @@ export type HookFetcherOptions = { url?: string method?: string } + +export type HookDeps = string | number | undefined[]