@shopify/shop-minis-react
Version:
React component library for Shopify Shop Minis with Tailwind CSS v4 support (source-only, requires TypeScript)
109 lines (97 loc) • 2.32 kB
text/typescript
import {useCallback, useEffect, useState} from 'react'
import debounce from 'lodash/debounce'
import {useShopActionInfiniteQuery} from '../../internal/reactQuery'
import {useShopActions} from '../../internal/useShopActions'
import {
PaginatedDataHookOptionsBase,
PaginatedDataHookReturnsBase,
Product,
ProductFilters,
ProductSearchSortBy,
} from '../../types'
export interface UseProductSearchParams extends PaginatedDataHookOptionsBase {
/**
* The search query.
*/
query: string
/**
* The filters to apply to the search.
*/
filters?: ProductFilters
/**
* The sort order of the results.
*/
sortBy?: ProductSearchSortBy
/**
* Whether to include sensitive products.
*/
includeSensitive?: boolean
}
interface UseProductSearchReturns extends PaginatedDataHookReturnsBase {
/**
* The products returned from the query.
*/
products: Product[] | null
/**
* Whether the user is typing.
*/
isTyping: boolean
}
export const useProductSearch = (
params: UseProductSearchParams
): UseProductSearchReturns => {
const {getProductSearch} = useShopActions()
const {
query,
filters,
sortBy,
includeSensitive = false,
skip = false,
...restParams
} = params ?? {}
const [debouncedQuery, setDebouncedQuery] = useState<string>(query)
// eslint-disable-next-line react-hooks/exhaustive-deps
const debouncedSetQuery = useCallback(
debounce((newQuery: string) => {
setDebouncedQuery(prev => {
// Only update if the query actually changed
if (prev === newQuery) return prev
return newQuery
})
}, 300),
[]
)
useEffect(() => {
debouncedSetQuery(query)
return () => {
debouncedSetQuery.cancel()
}
}, [query, debouncedSetQuery])
// Use our Shop Action infinite query helper
const {data, ...rest} = useShopActionInfiniteQuery(
[
'productSearch',
debouncedQuery,
filters,
sortBy,
includeSensitive,
restParams,
],
getProductSearch,
{
query: debouncedQuery,
filters,
sortBy,
includeSensitive,
...restParams,
},
{
skip: skip || debouncedQuery.trim().length === 0,
}
)
return {
...rest,
products: data,
isTyping: debouncedQuery !== query,
}
}