4
0
forked from crowetic/commerce

Updated useCart hook

This commit is contained in:
Luis Alvarez 2020-10-09 12:58:49 -05:00
parent 7758ea3199
commit 22ba0d7315
3 changed files with 54 additions and 23 deletions

View File

@ -1,21 +1,48 @@
import { HookFetcher, HookDeps } from '@lib/commerce/utils/types'
import { useCart as useCommerceCart } from '@lib/commerce/cart' import { useCart as useCommerceCart } from '@lib/commerce/cart'
import type { Cart } from '../api/cart' import type { Cart } from '../api/cart'
const defaultOpts = {
url: '/api/bigcommerce/cart',
}
export type { Cart } export type { Cart }
export function useCart() { export const fetcher: HookFetcher<Cart | null, HookDeps[]> = (
const cart = useCommerceCart<Cart | null>() options,
_,
// Uses a getter to only calculate the prop when required fetch
// cart.data is also a getter and it's better to not trigger it early ) => {
Object.defineProperty(cart, 'isEmpty', { return fetch({
get() { url: options?.url,
return Object.values(cart.data?.line_items ?? {}).every( query: options?.query,
(items) => !items.length
)
},
set: (x) => x,
}) })
return cart
} }
function extend(customFetcher: typeof fetcher) {
const useCart = () => {
const cart = useCommerceCart<Cart | null>(
[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)

View File

@ -1,22 +1,24 @@
import useSWR, { responseInterface } from 'swr' import useSWR, { responseInterface } from 'swr'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import { HookDeps, HookFetcher } from '../utils/types'
import { useCommerce } from '..' import { useCommerce } from '..'
const CART_API = '/api/bigcommerce/cart'
export type CartResponse<C> = responseInterface<C, Error> & { export type CartResponse<C> = responseInterface<C, Error> & {
isEmpty: boolean isEmpty: boolean
} }
function useCart<C>() { export function useCart<T>(
deps: [string | undefined, string | undefined, ...HookDeps[]],
fetcherFn: HookFetcher<T, HookDeps[]>
) {
const { fetcherRef, cartCookie } = useCommerce() const { fetcherRef, cartCookie } = useCommerce()
const fetcher = (url?: string, query?: string) => const fetcher = (url?: string, query?: string, ...args: HookDeps[]) =>
Cookies.get(cartCookie) ? fetcherRef.current({ url, query }) : null Cookies.get(cartCookie)
const response = useSWR([CART_API, undefined], fetcher, { ? fetcherFn({ url, query }, args, fetcherRef.current)
: null
const response = useSWR(deps, fetcher, {
revalidateOnFocus: false, revalidateOnFocus: false,
}) })
return Object.assign(response, { isEmpty: true }) as CartResponse<C> return Object.assign(response, { isEmpty: true }) as CartResponse<T>
} }
export { useCart }

View File

@ -20,3 +20,5 @@ export type HookFetcherOptions = {
url?: string url?: string
method?: string method?: string
} }
export type HookDeps = string | number | undefined[]