Use this file to discover all available pages before exploring further.
This is the React InstantSearch v7 documentation.
If you’re upgrading from v6, see the upgrade guide.
If you were using React InstantSearch Hooks,
this v7 documentation applies—just check for necessary changes.
To continue using v6, you can find the archived documentation.
Automatic Filtering and Boosting applies a category filter when users enter a .
You can use Query Categorization to
predict categories for your most popular queries.
If you enable Automatic Filtering and Boosting
the categories are automatically applied as filters.
Control Automatic Filtering and Boosting in your UI
If you want to have Automatic Filtering and Boosting on or off for all searches, you only need to enable the feature to filter the results automatically.If you want to let users turn Automatic Filtering and Boosting on or off, you can build an InstantSearch widget. This widget should inform users that the results are filtered. The widget should also let users remove any applied filters.
// connectAutoFiltering.tsimport type { Connector } from "instantsearch.js";export type AutoFilteringConnectorParams = {};export type AutoFilteringRenderState = { appliedFilters: Array<{ name: string; value: string; }>; cancelAutoFiltering(): void;};export type AutoFilteringWidgetDescription = { $$type: "algolia.beta.autoFiltering"; renderState: AutoFilteringRenderState; indexRenderState: {}; indexUiState: {};};type AutoFilteringConnector = Connector< AutoFilteringWidgetDescription, AutoFilteringConnectorParams>;type ConnectorState = { disabledQuery?: string; cancelAutoFiltering?: AutoFilteringRenderState["cancelAutoFiltering"];};// util function to set the query parameter (step 2)function setAutoFiltering(value, helper) { return helper.setQueryParameter("extensions", { queryCategorization: { enableAutoFiltering: value, }, });}type WidgetRenderStateWithResultsExtensions = Parameters< ReturnType<ReturnType<AutoFilteringConnector>>["getWidgetRenderState"]>[0] & { state: { extensions?: { queryCategorization?: { enableAutoFiltering?: boolean; }; }; }; results: { extensions?: { queryCategorization?: { normalizedQuery?: string; autofiltering?: { facetFilters?: string[]; }; }; }; };};export const connectAutoFiltering: AutoFilteringConnector = ( renderFn, unmountFn = () => {},) => { return function autoFiltering(widgetParams) { const connectorState: ConnectorState = {}; return { $$type: "algolia.beta.autoFiltering", init(initOptions) { const { instantSearchInstance } = initOptions; renderFn( { ...this.getWidgetRenderState(initOptions), instantSearchInstance, }, true, ); }, render(renderOptions) { const { instantSearchInstance } = renderOptions; renderFn( { ...this.getWidgetRenderState(renderOptions), instantSearchInstance, }, false, ); }, dispose() { unmountFn(); }, getWidgetUiState(uiState) { return uiState; }, getWidgetSearchParameters(searchParameters) { return searchParameters; }, getRenderState(renderState, renderOptions) { return { ...renderState, autoFiltering: this.getWidgetRenderState(renderOptions), }; }, // this is where the logic happens getWidgetRenderState({ results, helper, state, }: WidgetRenderStateWithResultsExtensions) { if (!connectorState.cancelAutoFiltering) { connectorState.cancelAutoFiltering = () => { // Disable auto filtering for next search setAutoFiltering(false, helper); helper.search(); // storing in the state the disabled query connectorState.disabledQuery = helper.getQuery().query; }; } // empty results case if (!results) { return { appliedFilters: [], cancelAutoFiltering: () => {}, widgetParams, }; } // enabling back auto filtering if the query has changed (step 3) if ( // "state" stores the current query parameters state.extensions?.queryCategorization?.enableAutoFiltering === false && connectorState.disabledQuery && results.query !== connectorState.disabledQuery ) { setAutoFiltering(true, helper); if (results.extensions.queryCategorization.normalizedQuery) { // if the current query has predicted categories, we refine the search with autofiltering enabled helper.search(); } } // Retrieving the applied filters (step 1) const facetFilters = results.extensions?.queryCategorization?.autofiltering ?.facetFilters || []; return { appliedFilters: facetFilters.map((facetFilter) => ({ name: facetFilter.split(":")[0], value: facetFilter.split(":")[1], })), cancelAutoFiltering: connectorState.cancelAutoFiltering, widgetParams, }; }, }; };};
With the useConnector Hook,
you can turn this connector into a useAutoFiltering Hook.
TypeScript
// useAutoFiltering.tsimport { useConnector } from "react-instantsearch";import { connectAutoFiltering } from "./connectAutoFiltering";import type { AdditionalWidgetProperties } from "react-instantsearch";import type { AutoFilteringConnectorParams, AutoFilteringWidgetDescription,} from "./connectAutoFiltering";export type AutoFilteringParams = AutoFilteringConnectorParams;export function useAutoFiltering( props?: AutoFilteringParams, additionalWidgetProperties?: AdditionalWidgetProperties,) { return useConnector< AutoFilteringConnectorParams, AutoFilteringWidgetDescription >(connectAutoFiltering, props, additionalWidgetProperties);}
And finally, you can build the UI around the hook.
React
// Autofiltering.tsximport React from "react";import { useAutoFiltering } from "./useAutoFiltering";export function AutoFiltering() { const { appliedFilters, cancelAutoFiltering } = useAutoFiltering( {}, { $$widgetType: "algolia.beta.autoFiltering", }, ); /** * Here you choose to display the applied filters in a banner with a button to disable autofiltering. * Only the last filter of the hierarchy is displayed here, but you can choose to display all of them if you want to. * It is entirely up to you how you choose to render the filters. */ if (appliedFilters.length === 0) { return null; } return ( <div style={{ border: "1px solid lightgray", borderRadius: "3px", margin: "1rem 0", padding: "1rem", }} > <span> <strong>Applied filter:</strong>{" "} </span> <span> {appliedFilters.pop().value}{" "} <button onClick={() => cancelAutoFiltering()}>×</button> </span> </div> );}
If you have a standard React InstantSearch implementation, you can copy and paste both the preceding snippets into your app.
However, ensure you tweak the final AutoFiltering component to fit your design.You can then place AutoFiltering in your app.