Methods and Access

These methods define the core search functionality that each provider must implement:

Data Fetching Methods

// Primary search method - returns paginated search results
abstract get(params?: SearchParams): Promise<SearchResponse<T>>

// SWR-compatible fetcher for infinite scroll integration
abstract fetcher(params: any): Promise<SearchResponse<Product>>

// SWR key generator for caching and pagination
abstract getKey(
  pageIndex: number,
  previousPageData: any,
): Record<string, any> | null

// Recommendations/suggestions method - returns popular search terms and products
abstract getRecommendations(params: { query: string }): Promise<{
  searches: string[]
  products: Product[]
  totalResults: number
}>

// Factory method for creating new instances
abstract createInstance(params: {
  queryParams?: QueryParams
  productsPerPage?: number
}): BaseSearchClient<T>

Internal Integration Methods

// Apply base parameters to the specific search provider
protected abstract applyBaseParamsToIntegration(): void

// Refresh facet/filter data when filters change
protected abstract refreshFilters(options?: { field?: string }): Promise<void>

State Accessors

// Get current collection context
public getCollection(): { handle: string; id: string }

// Get current sort setting
public getSort(): string

// Get available sort options
public getSortOptions(): Array<{
  key: string
  name: string
  sortName: string
}>

// Get current filters
public getFilters(): Record<string, Set<string>>

// Get formatted facets with counts
public getFilterState(): FormattedFacet[]

// Get pagination settings
public getProductsPerPage(): number
public getCurrentPage(): number

// Get last search response
public getLastResponse(): SearchResponse<T> | null

// Check if more results are available
public getHasMore(): boolean

State Modifiers

// Update sort option
public updateSort(sort: string): void

// Apply pending filter changes
public updateFilters(): void

// Add a single filter
public async setFilter(filter: {
  key: string
  value: string
}): Promise<FormattedFacet[]>

// Remove a single filter
public async removeFilter(filter: {
  key: string
  value: string
}): Promise<FormattedFacet[]>

// Reset all filters except collection filters
public async resetFilters(): Promise<FormattedFacet[]>

// Reset to previous filter state (cancel pending changes)
public async resetToPreviousFilters(): Promise<void>

// Update collection filter fields
public setCollectionFilterField({
  collectionHandle,
  collectionId,
}: {
  collectionHandle?: string
  collectionId?: string
}): void

Event Listeners

// Listen for sort changes
public onSortChange(callback: SortChangeCallback): () => void

// Listen for filter changes
public onFilterChange(callback: FilterChangeCallback): () => void

// Listen for filter state changes (facet counts)
public onFilterStateChange(callback: FilterStateChangeCallback): () => void

// Listen for collection changes
public onCollectionChange(callback: CollectionChangeCallback): () => void

// Listen for any search state change
public onSearchStateChange(callback: SearchStateChangeCallback): () => void

// Listen for all changes with current state
public onAllChanges(callback: SearchStateChangeCallback): () => void

Access Patterns

Getting a Search Client Instance

There are two main ways to access search clients in code.js blocks:

1. Through Context (Main Search/Collection Pages)

export default function ProductGrid({
  useSearchContext = () => ({ searchClient: null, isSearchClient: false }),
}) {
  const { searchClient, isSearchClient } = useSearchContext()

  // Use searchClient with hooks
  const { products, isLoading, ref } = useInfiniteScroll({
    searchClient: searchClient,
    // other params...
  })
}

ProductGrid Pattern: Used in ProductGrid and similar blocks. This pattern:

  • Uses useSearchContext() to get the main search client
  • Integrates with useInfiniteScroll for pagination
  • Handles both search client and fallback API modes

2. Through useSearchInstance (Carousels/Components)

export default function ProductCarousel({ useSearchInstance = (any) => null }) {
  const searchClient = useSearchInstance({
    searchParams: {
      collectionId: blockConfig.collectionId,
    },
  })

  const { products, isLoading } = useInfiniteScroll({
    searchClient,
    // other params...
  })
}

This creates an isolated search client instance that operates independently from the main layout-level search client. Any customizations or search operations performed on this instance will only affect this specific component, allowing you to have different search behavior for carousels, related products, or other sub-components without interfering with the primary search functionality of the page.

ProductCarousel Pattern: Used in ProductCarousel, TabbedProductCarousel, LargeProductCarousel and similar blocks. This pattern:

  • Uses useSearchInstance() to create isolated search instances
  • Ideal for components that need separate search state
  • Commonly used for related products, recommendations

Integration with Hooks

useInfiniteScroll

When searchClient is provided, the hook uses the search client's fetcher and getKey methods:

const { products, isLoading, ref, isReachingEnd } = useInfiniteScroll({
  searchClient: searchClient, // Uses searchClient.fetcher() and searchClient.getKey()
  productLimit: 50,
  direction: "vertical",
})

useRecommendations

When searchClient is provided, it uses the getRecommendations method:

const { products, searches, isLoading } = useRecommendations({
  searchClient: searchClient, // Uses searchClient.getRecommendations()
  query: "search term", // Required when using searchClient - query string for recommendations
  queryVariables: {
    appId: tapcartData.appId,
    language: "en",
  },
})

Note: When using a search client with useRecommendations, the query parameter is required and will be passed to the search client's getRecommendations() method.

Recommendations Pattern: Used in TrendingSearchResults, SearchResultsProducts and similar blocks. This pattern:

  • Uses useRecommendations hook with search client
  • Handles both search-based and trending recommendations
  • Supports caching and fallback states