From c2096a8ab4c5f3992379865a3f3c84c369a60b84 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Fri, 9 Oct 2020 10:36:23 -0500 Subject: [PATCH] Make use-add-item hook extendable --- lib/bigcommerce/cart/use-add-item.tsx | 49 +++++++++++++++++++-------- lib/commerce/cart/use-add-item.tsx | 8 +++-- lib/commerce/index.tsx | 11 +----- lib/commerce/utils/types.ts | 27 +++++++++++++++ 4 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 lib/commerce/utils/types.ts diff --git a/lib/bigcommerce/cart/use-add-item.tsx b/lib/bigcommerce/cart/use-add-item.tsx index 924eeb6eb..811d4f9c3 100644 --- a/lib/bigcommerce/cart/use-add-item.tsx +++ b/lib/bigcommerce/cart/use-add-item.tsx @@ -1,12 +1,21 @@ import { useCallback } from 'react' -import type { Fetcher } from '@lib/commerce' +import { HookFetcher } from '@lib/commerce/utils/types' import { default as useCartAddItem } from '@lib/commerce/cart/use-add-item' import type { ItemBody, AddItemBody } from '../api/cart' import { Cart, useCart } from '.' export type UpdateItemInput = ItemBody -function fetcher(fetch: Fetcher, { item }: AddItemBody) { +const defaultOpts = { + url: '/api/bigcommerce/cart', + method: 'POST', +} + +export const fetcher: HookFetcher = ( + options, + { item }, + fetch +) => { if ( item.quantity && (!Number.isInteger(item.quantity) || item.quantity! < 1) @@ -16,19 +25,31 @@ function fetcher(fetch: Fetcher, { item }: AddItemBody) { ) } - return fetch({ url: '/api/bigcommerce/cart', method: 'POST', body: { item } }) + return fetch({ + url: options.url!, + method: options.method!, + body: { item }, + }) } -export default function useAddItem() { - const { mutate } = useCart() - const fn = useCartAddItem(fetcher) +function extend(customFetcher: typeof fetcher) { + const useAddItem = () => { + const { mutate } = useCart() + const fn = useCartAddItem(defaultOpts, customFetcher) - return useCallback( - async function addItem(input: UpdateItemInput) { - const data = await fn({ item: input }) - await mutate(data, false) - return data - }, - [fn, mutate] - ) + return useCallback( + async function addItem(input: UpdateItemInput) { + const data = await fn({ item: input }) + await mutate(data, false) + return data + }, + [fn, mutate] + ) + } + + useAddItem.extend = extend + + return useAddItem } + +export default extend(fetcher) diff --git a/lib/commerce/cart/use-add-item.tsx b/lib/commerce/cart/use-add-item.tsx index 6433e4393..5445f9e11 100644 --- a/lib/commerce/cart/use-add-item.tsx +++ b/lib/commerce/cart/use-add-item.tsx @@ -1,14 +1,16 @@ import { useCallback } from 'react' -import { Fetcher, useCommerce } from '..' +import { HookFetcher, HookFetcherOptions } from '../utils/types' +import { useCommerce } from '..' export default function useAddItem( - fetcher: (fetch: Fetcher, input: Input) => T | Promise + options: HookFetcherOptions, + fetcher: HookFetcher ) { const { fetcherRef } = useCommerce() return useCallback( function addItem(input: Input) { - return fetcher(fetcherRef.current, input) + return fetcher(options, input, fetcherRef.current) }, [fetcher] ) diff --git a/lib/commerce/index.tsx b/lib/commerce/index.tsx index 0cdb43851..7d0fefbde 100644 --- a/lib/commerce/index.tsx +++ b/lib/commerce/index.tsx @@ -6,6 +6,7 @@ import { useMemo, useRef, } from 'react' +import { Fetcher } from './utils/types' const Commerce = createContext(null) @@ -20,16 +21,6 @@ export type CommerceConfig = { cartCookie: string } -export type Fetcher = (options: FetcherOptions) => T | Promise - -export type FetcherOptions = { - url?: string - query?: string - method?: string - variables?: any - body?: any -} - export function CommerceProvider({ children, config }: CommerceProps) { if (!config) { throw new Error('CommerceProvider requires a valid config object') diff --git a/lib/commerce/utils/types.ts b/lib/commerce/utils/types.ts new file mode 100644 index 000000000..980e78e9b --- /dev/null +++ b/lib/commerce/utils/types.ts @@ -0,0 +1,27 @@ +// Core fetcher added by CommerceProvider +export type Fetcher = (options: FetcherOptions) => T | Promise + +export type FetcherOptions = { + url?: string + query?: string + method?: string + variables?: any + body?: any +} + +export type HookFetcher = ( + options: HookFetcherOptions, + input: Input, + fetch: Fetcher +) => T | Promise + +// export type HookFetcher = ( +// options: FetcherOptions, +// fetch: Fetcher +// ) => T | Promise + +export type HookFetcherOptions = { + query?: string + url?: string + method?: string +}