Collection store
The createCollectionStore function creates a store that holds the customer's filter and sort choices for a collection or search page. Use the store to change filters and sort from your UI, navigate to the new URL after each change, and show a loading state until your loader returns new results.
In React and Vue apps, use CollectionProvider, which creates the store for you.
Import createCollectionStore, createCollectionReconciler, and createInitialCollectionState from @shopify/hydrogen.
Anchor to Filter and sort storeFilter and sort store
Creates a store that holds the customer's filter and sort choices for one collection. Your loader fetches the products.
The store reads its starting filters and sort from , or from when you omit . In React, use , which creates the store for you and keeps the store in sync with the URL.
- Anchor to optionsoptionsoptionsCreateCollectionStoreOptionsCreateCollectionStoreOptionsrequiredrequired
The collection data, the current URL search string, and the browse change callback.
A store with methods that change the filters and sort and report the loading status.
CreateCollectionStoreOptions
Options for `createCollectionStore`.
- data
The collection handle and the search string that your loader fetched products for.
CollectionData - onBrowseChange
Runs after each filter or sort change from a store method. Navigate to the new URL in the callback. Syncing from URL params and settling the store don't run the callback.
() => void - urlSearch
Current URL search string from your router, with or without a leading `?`. Defaults to the `dataSearch` string from `data`.
string
CollectionData
The collection handle and the search string that your loader fetched products for.
- dataSearch
Search string that your loader used for the Storefront API query, with or without a leading `?`. Pass the exact string. The status stays `loading` until this string and the URL search hold the same filters, sort key, and sort direction.
string - handle
Collection handle, such as `shoes`. On search pages, pass a handle such as `search:${term}` to keep separate filter and sort state for each search term. When the handle changes, the collection provider reads the filters and sort from the URL again.
string
CollectionStore
Holds the customer's filter and sort choices for a collection or search page, and reports when new results are loading. Each change updates the state right away and sets the status to `loading`. Your app then navigates, your loader fetches the new products, and you call `settle()` when the data arrives. The collection provider navigates and settles the store for you. The store keeps the sort direction only for the price, title, created, and ID sort keys. For other sort keys, `reverse` reads `false`. The store keeps at most one availability filter. Adding a second availability filter removes both availability filters.
- getFilterRemovalUrl
Returns a query string with the store's filters and sort, minus the given filter. Use the query string in remove-filter links and buttons. The string starts with `?` and leaves out URL params that the store doesn't manage.
(filter: ProductFilter) => string - getState
Returns the current filter and sort state.
() => CollectionState - handleFormSubmit
Applies a submitted filter form to the store. The form's filter fields replace the active filters. The sort changes only when the form includes a `sort_by` field. Call `event.preventDefault()` first, or the browser submits the form and leaves the page. The method throws a `TypeError` when the event target isn't a form element.
(event: SubmitEvent) => void - matchesParams
Returns `true` when the URL search params hold the same filters and sort as the store.
(searchParams: URLSearchParams) => boolean - reset
Clears all filters, restores the collection's default sort, and sets the status to `loading`.
() => void - serializeToParams
Returns the filters and sort as URL search params. The result holds only the `filter.*` and `sort_by` keys.
() => URLSearchParams - setFilters
Replaces the active filters and sets the status to `loading`.
(filters: ProductFilter[]) => void - setOnBrowseChange
Sets the callback that runs after each filter or sort change. Navigate to the new URL in the callback. Pass `null` to remove the callback.
(callback: () => void) => void - setSortByValue
Applies the sort key and direction from a Liquid-compatible `sort_by` value, such as `price-ascending`. An unrecognized value sets the sort key to `COLLECTION_DEFAULT`.
(sortByValue: string) => void - setSortKey
Changes the sort key and direction, then sets the status to `loading`. Omit `reverse` to sort in ascending order.
(sortKey: ProductCollectionSortKeys, reverse?: boolean) => void - settle
Sets the status to `idle`. Call the method when your loader returns the new products.
() => void - subscribe
Calls the listener on every state change. Returns a function that unsubscribes the listener.
(listener: (state: CollectionState) => void) => () => void - syncFromParams
Updates the store from URL search params that differ from the current state. Call the method when the URL changes outside the store, such as on back or forward navigation. The method sets the status to `loading` and skips the browse change callback.
(searchParams: URLSearchParams) => void - toggleFilter
Adds the filter when it's inactive and removes the filter when it's active, then sets the status to `loading`.
(filter: ProductFilter) => void - toggleFilterInput
Toggles the filter in a filter value's `input` JSON string from the Storefront API. The method does nothing when the string isn't valid JSON.
(input: string) => void
CollectionState
The customer's filter and sort choices and the loading status. Products, product counts, available filters, and the collection ID come from your loader data.
- filters
Active product filters, matching the `filter.*` URL params.
ProductFilter[] - handle
Collection handle, such as `shoes`.
string - reverse
`true` for a descending sort. The URL's sort value then ends in `-descending`.
boolean - sortKey
Storefront API sort key, or `undefined` for the collection's default sort.
ProductCollectionSortKeys | undefined - status
Reads `loading` from a filter or sort change until the store settles, and `idle` when the results match the filters and sort. Show a loading state while the value is `loading`.
'idle' | 'loading'
TypeScript
Examples
Description
Create the store from loader data and the current URL. This example navigates whenever filters or sort change.
TypeScript
import { createCollectionStore } from "@shopify/hydrogen"; declare const loaderData: { collection: { handle: string; dataSearch: string } }; declare function navigate(to: { search: string }): Promise<void>; declare function renderFilters(filters: unknown[]): void; function buildBrowseSearch(): string { const params = new URLSearchParams(window.location.search); for (const key of Array.from(params.keys())) { if (key === "sort_by" || key.startsWith("filter.")) params.delete(key); } params.delete("before"); params.delete("after"); for (const [key, value] of store.serializeToParams()) params.append(key, value); return params.toString(); } const store = createCollectionStore({ data: loaderData.collection, urlSearch: window.location.search, onBrowseChange: async () => { await navigate({ search: buildBrowseSearch() }); store.settle(); }, }); store.subscribe((state) => renderFilters(state.filters));Description
Change filters and sort, then settle the store to return its status from `loading` to `idle`.
TypeScript
import { createCollectionStore } from "@shopify/hydrogen"; const store = createCollectionStore({ data: { handle: "shoes", dataSearch: "" }, }); store.setFilters([{ tag: "sale" }]); store.setSortByValue("price-descending"); console.log(store.getState().status); store.settle(); console.log(store.getState().status);
Anchor to URL and loader syncURL and loader sync
Creates a reconciler that keeps the URL, your loader data, and a collection store in sync while the customer changes filters and sort.
Use a reconciler to connect a collection store to a router that has no Hydrogen binding. In React, use .
- Anchor to callbackscallbackscallbacksReconcilerCallbacksReconcilerCallbacksrequiredrequired
The functions that return the store and the URL search string and navigate your router.
- Anchor to initialPrevUrlSearchinitial
Prev Url Searchinitial Prev Url Search stringstringDefault: ""Default: "" The current URL search string, which the first
reconcile()call compares against. Defaults to an empty string.
A reconciler. Call
reconcile()on URL changes, and registeras the store's browse change callback.
ReconcilerCallbacks
Functions that connect a collection reconciler to your router and your collection store.
- emitChange
Navigates your router to the search string. The string starts with `?`, or is empty when no params remain.
(searchString: string) => void - getStore
Returns the collection store.
() => CollectionStore - readUrlSearch
Returns the current URL search string from your router.
() => string
CollectionReconciler
Keeps the URL, your loader data, and a collection store in sync while the customer changes filters and sort.
- handleBrowseChange
Builds the next search string from the store's filters and sort, and passes the string to `emitChange`. Register the method as the store's browse change callback. The new search string keeps every URL param that the store doesn't manage and drops the `before` and `after` pagination cursors.
() => void - reconcile
Brings the store in line with the URL. Call the method each time the URL search or the `dataSearch` string changes. The method settles the store when your loader data matches the URL. During rapid filter changes, the method skips intermediate URLs. A URL that the reconciler didn't request counts as external navigation, such as back or forward.
(urlSearch: string, dataSearch: string) => void - reset
Clears pending navigation. Call the method when you replace the store.
(newPrevUrlSearch: string) => void
TypeScript
Examples
Description
Connect a collection store to your router. The reconciler navigates when the customer changes a filter or the sort, and the example calls `reconcile()` after each navigation loads new data.
TypeScript
import { createCollectionReconciler, createCollectionStore } from "@shopify/hydrogen"; declare const data: { handle: string; dataSearch: string }; declare const router: { getSearch: () => string; navigate: (to: string) => void; }; const store = createCollectionStore({ data, urlSearch: router.getSearch() }); const reconciler = createCollectionReconciler( { getStore: () => store, readUrlSearch: router.getSearch, emitChange: (search) => router.navigate(`${location.pathname}${search}`), }, router.getSearch(), ); store.setOnBrowseChange(() => reconciler.handleBrowseChange()); export function onRouteLoaded(dataSearch: string) { reconciler.reconcile(router.getSearch(), dataSearch); }
Anchor to Initial stateInitial state
Creates collection state with no filters and the default sort for a collection handle.
- Anchor to handlehandlehandlestringstringrequiredrequired
Collection handle, such as
shoes.
A state with no filters, the collection's default sort, an ascending direction, and an idle status.
TypeScript
Examples
Description
Create a blank state for the `shoes` collection. This example serializes the blank state to an empty search string.
TypeScript
import { createInitialCollectionState, serializeCollectionParams } from "@shopify/hydrogen"; const state = createInitialCollectionState("shoes"); const search = serializeCollectionParams(state).toString();