Skip to main content
The InstantSearchOptions type defines all configuration options available when creating an InstantSearch instance.

Type Signature

type InstantSearchOptions<
  TUiState extends UiState = UiState,
  TRouteState = TUiState
> = {
  indexName?: string;
  compositionID?: string;
  searchClient: SearchClient | CompositionClient;
  numberLocale?: string;
  searchFunction?: (helper: AlgoliaSearchHelper) => void;
  onStateChange?: (params: {
    uiState: TUiState;
    setUiState: (
      uiState: TUiState | ((previousUiState: TUiState) => TUiState)
    ) => void;
  }) => void;
  initialUiState?: TUiState;
  stalledSearchDelay?: number;
  routing?: RouterProps<TUiState, TRouteState> | boolean;
  insights?: InsightsProps | boolean;
  insightsClient?: AlgoliaInsightsClient;
  future?: {
    preserveSharedStateOnUnmount?: boolean;
    persistHierarchicalRootCount?: boolean;
  };
}

Required Options

searchClient
SearchClient | CompositionClient
required
The search client to plug to InstantSearch.js. This is the only required option.Using Algolia’s default search client:
import algoliasearch from 'algoliasearch/lite';

const searchClient = algoliasearch(
  'YourApplicationID',
  'YourSearchOnlyAPIKey'
);

instantsearch({
  indexName: 'products',
  searchClient
});
Using a custom search client:
const customSearchClient = {
  search(requests) {
    // Fetch and return search results based on requests
    return fetch('/api/search', {
      method: 'POST',
      body: JSON.stringify({ requests })
    }).then(res => res.json());
  },
  searchForFacetValues(requests) {
    // Fetch and return facet values based on requests
    return fetch('/api/facets', {
      method: 'POST',
      body: JSON.stringify({ requests })
    }).then(res => res.json());
  }
};

instantsearch({
  indexName: 'products',
  searchClient: customSearchClient
});

Index Configuration

indexName
string
The name of the main index. If no indexName is provided, you must manually add an index widget.
instantsearch({
  indexName: 'products',
  searchClient
});
compositionID
string
The objectID of the composition. If this is provided, the composition API will be used for search.
Multi-index search is not supported when using compositionID.
instantsearch({
  compositionID: 'my_composition_id',
  searchClient
});

State Management

initialUiState
TUiState
Injects an initial UI state to the InstantSearch instance. Use this option to provide an initial state to widgets.
The state is only used for the first search. To unconditionally pass additional parameters to the Algolia API, use the configure widget.
instantsearch({
  indexName: 'products',
  searchClient,
  initialUiState: {
    products: {
      query: 'laptop',
      page: 1,
      refinementList: {
        brand: ['Apple', 'Samsung']
      }
    }
  }
});
onStateChange
function
Function called when the state changes. Using this function makes the instance controlled, meaning you become responsible for updating the UI state with setUiState.Parameters:
  • uiState (TUiState) - The next UI state
  • setUiState (function) - Function to update the UI state
instantsearch({
  indexName: 'products',
  searchClient,
  onStateChange({ uiState, setUiState }) {
    // Log state changes
    console.log('State changed:', uiState);
    
    // Apply custom transformations
    const transformedState = {
      ...uiState,
      products: {
        ...uiState.products,
        // Add custom logic here
      }
    };
    
    // Update the UI state
    setUiState(transformedState);
  }
});

Routing

routing
RouterProps<TUiState, TRouteState> | boolean
default:"false"
Router configuration used to save the UI state into the URL or any other client-side persistence. Pass true to use default URL options.Simple routing (boolean):
instantsearch({
  indexName: 'products',
  searchClient,
  routing: true
});
Advanced routing configuration:
instantsearch({
  indexName: 'products',
  searchClient,
  routing: {
    router: instantsearch.routers.history(),
    stateMapping: instantsearch.stateMappings.simple()
  }
});
See the routing guide for more details.

Insights and Analytics

insights
InsightsProps | boolean
default:"false"
Enables the Insights middleware and loads the Insights library if not already loaded.The Insights middleware automatically sends view and click events, and lets you set up custom events.Simple insights (boolean):
instantsearch({
  indexName: 'products',
  searchClient,
  insights: true
});
Advanced insights configuration:
instantsearch({
  indexName: 'products',
  searchClient,
  insights: {
    insightsClient: window.aa,
    insightsInitParams: {
      useCookie: true,
      cookieDuration: 30 * 24 * 60 * 60 * 1000 // 30 days
    }
  }
});
insightsClient
AlgoliaInsightsClient
Deprecated. This property is still supported in 4.x releases, but not further. Use the insights middleware instead.
The instance of search-insights to use for sending insights events inside widgets.See the migration guide for more information.

UI Customization

numberLocale
string
The locale used to display numbers. This will be passed to Number.prototype.toLocaleString().
instantsearch({
  indexName: 'products',
  searchClient,
  numberLocale: 'fr-FR' // Format numbers using French locale
});
Example output:
  • en-US: 1,234.56
  • fr-FR: 1 234,56
  • de-DE: 1.234,56

Search Behavior

stalledSearchDelay
number
default:"200"
Time in milliseconds before a search is considered stalled. When a search exceeds this delay, the status property changes to "stalled".
instantsearch({
  indexName: 'products',
  searchClient,
  stalledSearchDelay: 500 // Wait 500ms before considering search stalled
});

search.on('render', () => {
  if (search.status === 'stalled') {
    console.log('Search is taking longer than expected');
  }
});
searchFunction
(helper: AlgoliaSearchHelper) => void
Deprecated. Use onStateChange instead.
A hook that will be called each time a search needs to be done. You’re responsible for calling helper.search().This option allows you to avoid doing searches at page load, for example.
instantsearch({
  indexName: 'products',
  searchClient,
  searchFunction(helper) {
    const query = helper.state.query;
    
    if (query === '') {
      // Don't search if query is empty
      return;
    }
    
    helper.search();
  }
});

Future Flags

future
object
Options for opting into future breaking changes before the next major version.
future.preserveSharedStateOnUnmount
boolean
default:"false"
Changes the way dispose is used in the InstantSearch lifecycle.
  • If false (default): Each widget unmounting will remove its state, even if there are multiple widgets reading that UI state.
  • If true: Each widget unmounting will only remove its own state if it’s the last of its type. This allows dynamically adding and removing widgets without losing their state.
instantsearch({
  indexName: 'products',
  searchClient,
  future: {
    preserveSharedStateOnUnmount: true
  }
});
This will become the default behavior in the next major version.
future.persistHierarchicalRootCount
boolean
default:"false"
Changes the way root levels of hierarchical facets have their count displayed.
  • If false (default): The count of the refined root level is updated to match the count of the actively refined parent level.
  • If true: The count of the root level stays the same as the count of all children levels.
instantsearch({
  indexName: 'products',
  searchClient,
  future: {
    persistHierarchicalRootCount: true
  }
});
This will become the default behavior in the next major version.

Complete Example

import instantsearch from 'instantsearch.js';
import algoliasearch from 'algoliasearch/lite';
import { createInsightsMiddleware } from 'instantsearch.js/es/middlewares';

const searchClient = algoliasearch(
  'YourApplicationID',
  'YourSearchOnlyAPIKey'
);

const search = instantsearch({
  // Index configuration
  indexName: 'products',
  searchClient,

  // State management
  initialUiState: {
    products: {
      query: 'laptop',
      refinementList: {
        brand: ['Apple']
      }
    }
  },
  onStateChange({ uiState, setUiState }) {
    // Track state changes
    console.log('State:', uiState);
    setUiState(uiState);
  },

  // Routing
  routing: {
    router: instantsearch.routers.history(),
    stateMapping: instantsearch.stateMappings.simple()
  },

  // Insights
  insights: {
    insightsClient: window.aa,
    insightsInitParams: {
      useCookie: true
    }
  },

  // UI customization
  numberLocale: 'en-US',
  stalledSearchDelay: 300,

  // Future flags
  future: {
    preserveSharedStateOnUnmount: true,
    persistHierarchicalRootCount: false
  }
});

search.start();

TypeScript Example

import instantsearch from 'instantsearch.js';
import algoliasearch from 'algoliasearch/lite';
import type { InstantSearchOptions, UiState } from 'instantsearch.js';

interface ProductsUiState extends UiState {
  products: {
    query?: string;
    page?: number;
    refinementList?: {
      brand?: string[];
      category?: string[];
    };
    range?: {
      price?: {
        min?: number;
        max?: number;
      };
    };
  };
}

const searchClient = algoliasearch(
  'YourApplicationID',
  'YourSearchOnlyAPIKey'
);

const options: InstantSearchOptions<ProductsUiState> = {
  indexName: 'products',
  searchClient,
  initialUiState: {
    products: {
      query: '',
      refinementList: {
        brand: []
      }
    }
  },
  routing: true,
  insights: true
};

const search = instantsearch<ProductsUiState>(options);
search.start();