Final touches to the hook handler type

This commit is contained in:
Luis Alvarez 2021-02-10 15:10:48 -05:00
parent 0eeb290eb0
commit 271ed01631
4 changed files with 36 additions and 85 deletions

View File

@ -54,12 +54,11 @@ const useCart: HookHandler<
url: '/api/bigcommerce/cart', url: '/api/bigcommerce/cart',
method: 'GET', method: 'GET',
}, },
swrOptions: {
revalidateOnFocus: false,
},
normalizer: normalizeCart, normalizer: normalizeCart,
useHook({ input, useData }) { useHook({ input, useData }) {
const response = useData({ input }) const response = useData({
swrOptions: { revalidateOnFocus: false, ...input.swrOptions },
})
return useMemo( return useMemo(
() => () =>
@ -74,16 +73,6 @@ const useCart: HookHandler<
[response] [response]
) )
}, },
onResponse(response) {
return Object.create(response, {
isEmpty: {
get() {
return (response.data?.lineItems.length ?? 0) <= 0
},
enumerable: true,
},
})
},
} }
const useWishlist: HookHandler< const useWishlist: HookHandler<
@ -98,19 +87,6 @@ const useWishlist: HookHandler<
url: '/api/bigcommerce/wishlist', url: '/api/bigcommerce/wishlist',
method: 'GET', method: 'GET',
}, },
swrOptions: {
revalidateOnFocus: false,
},
onResponse(response) {
return Object.create(response, {
isEmpty: {
get() {
return (response.data?.lineItems.length ?? 0) <= 0
},
enumerable: true,
},
})
},
} }
export const bigcommerceProvider = { export const bigcommerceProvider = {

View File

@ -1,7 +1,11 @@
import { useMemo } from 'react'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import type { Cart } from '../types' import type { Cart } from '../types'
import type { Prop, HookFetcherFn, UseHookInput } from '../utils/types' import type {
Prop,
HookFetcherFn,
UseHookInput,
UseHookResponse,
} from '../utils/types'
import useData from '../utils/use-data-2' import useData from '../utils/use-data-2'
import { Provider, useCommerce } from '..' import { Provider, useCommerce } from '..'
@ -14,12 +18,12 @@ export type UseCartHandler<P extends Provider> = Prop<
'useCart' 'useCart'
> >
export type CartResponse<P extends Provider> = ReturnType<
Prop<UseCartHandler<P>, 'onResponse'>
>
export type UseCartInput<P extends Provider> = UseHookInput<UseCartHandler<P>> export type UseCartInput<P extends Provider> = UseHookInput<UseCartHandler<P>>
export type CartResponse<P extends Provider> = UseHookResponse<
UseCartHandler<P>
>
export type UseCart<P extends Provider> = Partial< export type UseCart<P extends Provider> = Partial<
UseCartInput<P> UseCartInput<P>
> extends UseCartInput<P> > extends UseCartInput<P>
@ -36,8 +40,6 @@ export const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
return data && normalize ? normalize(data) : data return data && normalize ? normalize(data) : data
} }
type X = UseCartInput<Provider>
export default function useCart<P extends Provider>( export default function useCart<P extends Provider>(
input: UseCartInput<P> = {} input: UseCartInput<P> = {}
) { ) {
@ -46,49 +48,24 @@ export default function useCart<P extends Provider>(
const provider = providerRef.current const provider = providerRef.current
const opts = provider.cart?.useCart const opts = provider.cart?.useCart
const { swrOptions, ...hookInput } = input
return opts?.useHook!({
input: hookInput,
swrOptions,
useData(ctx) {
const fetcherFn = opts?.fetcher ?? fetcher const fetcherFn = opts?.fetcher ?? fetcher
const useHook = opts?.useHook ?? ((ctx) => ctx.useData())
const wrapper: typeof fetcher = (context) => { const wrapper: typeof fetcher = (context) => {
context.input.cartId = Cookies.get(cartCookie) context.input.cartId = Cookies.get(cartCookie)
return fetcherFn(context) return fetcherFn(context)
} }
return useHook({
input,
useData(ctx) {
const response = useData( const response = useData(
{ { ...opts, fetcher: wrapper },
...opts,
fetcher: wrapper,
swrOptions: {
...opts.swrOptions,
...(ctx?.swrOptions ?? swrOptions),
},
},
ctx?.input ?? [], ctx?.input ?? [],
provider.fetcher ?? fetcherRef.current provider.fetcher ?? fetcherRef.current,
ctx?.swrOptions ?? input.swrOptions
) )
return response return response
}, },
}) })
// console.log(i)
// const fetcherFn = opts?.fetcher ?? fetcher
// const wrapper: typeof fetcher = (context) => {
// context.input.cartId = Cookies.get(cartCookie)
// return fetcherFn(context)
// }
// const response = useData(
// { ...opts, fetcher: wrapper },
// opts?.input ? opts.input(input ?? {}) : [],
// provider.fetcher ?? fetcherRef.current
// )
// const memoizedResponse = useMemo(
// () => (opts?.onResponse ? opts.onResponse(response) : response),
// [response]
// )
// return memoizedResponse as CartResponse<P>
} }

View File

@ -71,19 +71,13 @@ export type HookHandler<
// Custom state added to the response object of SWR // Custom state added to the response object of SWR
State = {} State = {}
> = { > = {
input?(
input: Input & { swrOptions?: SwrOptions<Data, FetchInput, Result> }
): HookFetchInput | HookSwrInput
useHook?(context: { useHook?(context: {
input: Input input: Input & { swrOptions?: SwrOptions<Data, FetchInput, Result> }
swrOptions?: SwrOptions<Data, FetchInput, Result>
useData(context?: { useData(context?: {
input?: HookFetchInput | HookSwrInput input?: HookFetchInput | HookSwrInput
swrOptions?: SwrOptions<Data, FetchInput, Result> swrOptions?: SwrOptions<Data, FetchInput, Result>
}): ResponseState<Data> }): ResponseState<Data>
}): ResponseState<Data> & State }): ResponseState<Data> & State
swrOptions?: SwrOptions<Data, FetchInput, Result>
onResponse?(response: ResponseState<Data>): ResponseState<Data> & State
fetchOptions?: HookFetcherOptions fetchOptions?: HookFetcherOptions
fetcher?: HookFetcherFn<Data, FetchInput, Result, Body> fetcher?: HookFetcherFn<Data, FetchInput, Result, Body>
normalizer?(data: Result): Data normalizer?(data: Result): Data
@ -104,8 +98,10 @@ export type UseHookParameters<H extends HookHandler<any>> = Parameters<
Prop<H, 'useHook'> Prop<H, 'useHook'>
> >
export type UseHookResponse<H extends HookHandler<any>> = ReturnType<
Prop<H, 'useHook'>
>
export type UseHookInput< export type UseHookInput<
H extends HookHandler<any> H extends HookHandler<any>
> = UseHookParameters<H>[0]['input'] & { > = UseHookParameters<H>[0]['input']
swrOptions?: UseHookParameters<H>[0]['swrOptions']
}

View File

@ -5,6 +5,7 @@ import type {
HookFetchInput, HookFetchInput,
PickRequired, PickRequired,
Fetcher, Fetcher,
SwrOptions,
} from './types' } from './types'
import defineProperty from './define-property' import defineProperty from './define-property'
import { CommerceError } from './errors' import { CommerceError } from './errors'
@ -25,10 +26,11 @@ export type UseData = <
'fetcher' 'fetcher'
>, >,
input: HookFetchInput | HookSwrInput, input: HookFetchInput | HookSwrInput,
fetcherFn: Fetcher fetcherFn: Fetcher,
swrOptions?: SwrOptions<Data, FetchInput, Result>
) => ResponseState<Data> ) => ResponseState<Data>
const useData: UseData = (options, input, fetcherFn) => { const useData: UseData = (options, input, fetcherFn, swrOptions) => {
const hookInput = Array.isArray(input) ? input : Object.entries(input) const hookInput = Array.isArray(input) ? input : Object.entries(input)
const fetcher = async ( const fetcher = async (
url?: string, url?: string,
@ -64,7 +66,7 @@ const useData: UseData = (options, input, fetcherFn) => {
: null : null
}, },
fetcher, fetcher,
options.swrOptions swrOptions
) )
if (!('isLoading' in response)) { if (!('isLoading' in response)) {