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 } export 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(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, } } /** * The `useProductSearch` hook fetches products based on a search query. * * > Note: In order to filter products by category, you can check [Shopify's Product Taxonomy](https://shopify.github.io/product-taxonomy/releases/latest/). Then use the GID of the category. For example, to filter products in the Electronics category, you would use: ["gid://shopify/TaxonomyCategory/el"] * @publicDocs */ export type UseProductSearchGeneratedType = ( params: UseProductSearchParams ) => UseProductSearchReturns