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
Updated about 9 hours ago