Skip to main content
The useInstantSearch hook provides access to the InstantSearch instance and the current search state.

Import

import { useInstantSearch } from 'react-instantsearch';

Parameters

catchError
boolean
default:"false"
Whether to catch errors from the search lifecycle. When true, errors are caught and available in the error property.
const { error } = useInstantSearch({ catchError: true });

Returns

uiState
UiState
The current UI state for all indices.
const { uiState } = useInstantSearch();
console.log(uiState.products.query); // Current query
console.log(uiState.products.refinementList); // Active refinements
setUiState
(state: UiState | (prev: UiState) => UiState) => void
Function to update the UI state.
const { setUiState } = useInstantSearch();

// Set directly
setUiState({ products: { query: 'phone' } });

// Use function updater
setUiState((prev) => ({
  ...prev,
  products: {
    ...prev.products,
    query: 'phone',
  },
}));
indexUiState
IndexUiState
The UI state for the current index.
const { indexUiState } = useInstantSearch();
console.log(indexUiState.query);
console.log(indexUiState.refinementList);
setIndexUiState
(state: IndexUiState | (prev: IndexUiState) => IndexUiState) => void
Function to update the UI state for the current index.
const { setIndexUiState } = useInstantSearch();
setIndexUiState({ query: 'phone', page: 1 });
renderState
RenderState
The render state for all indices, containing widget states.
const { renderState } = useInstantSearch();
console.log(renderState.products.searchBox.query);
indexRenderState
IndexRenderState
The render state for the current index.
const { indexRenderState } = useInstantSearch();
console.log(indexRenderState.searchBox.query);
results
SearchResults | null
The search results from Algolia.
const { results } = useInstantSearch();
console.log(results?.nbHits);
scopedResults
ScopedResult[]
Results for all indices in a multi-index search.
const { scopedResults } = useInstantSearch();
scopedResults.forEach(({ indexId, results }) => {
  console.log(`${indexId}: ${results.nbHits} hits`);
});
status
'idle' | 'loading' | 'stalled' | 'error'
The current status of the search.
const { status } = useInstantSearch();
if (status === 'loading') return <div>Loading...</div>;
if (status === 'error') return <div>Error occurred</div>;
error
Error | undefined
The error that occurred during search (only when status === 'error').
const { error, status } = useInstantSearch({ catchError: true });
if (status === 'error') {
  console.error(error);
}
refresh
() => void
Function to refresh the search results by clearing the cache.
const { refresh } = useInstantSearch();

// Refresh after an indexing operation
await updateIndex();
refresh();
addMiddlewares
(...middlewares: Middleware[]) => () => void
Function to add middlewares to InstantSearch. Returns a cleanup function.
const { addMiddlewares } = useInstantSearch();

useEffect(() => {
  const removeMiddlewares = addMiddlewares(
    myCustomMiddleware(),
    anotherMiddleware()
  );
  
  return removeMiddlewares; // Cleanup on unmount
}, [addMiddlewares]);

Examples

Access Current Query

function QueryDisplay() {
  const { indexUiState } = useInstantSearch();

  return (
    <div>
      {indexUiState.query ? (
        <p>Searching for: {indexUiState.query}</p>
      ) : (
        <p>No search query</p>
      )}
    </div>
  );
}

Clear All Refinements

function ClearAllButton() {
  const { setIndexUiState } = useInstantSearch();

  const clearAll = () => {
    setIndexUiState((prev) => ({
      ...prev,
      refinementList: {},
      menu: {},
      range: {},
    }));
  };

  return <button onClick={clearAll}>Clear All Filters</button>;
}

Loading Indicator

function LoadingIndicator() {
  const { status } = useInstantSearch();

  if (status === 'loading' || status === 'stalled') {
    return (
      <div className="loading">
        <div className="spinner" />
        {status === 'stalled' && <p>Still loading...</p>}
      </div>
    );
  }

  return null;
}

Error Handling

function SearchError() {
  const { status, error } = useInstantSearch({ catchError: true });

  if (status === 'error') {
    return (
      <div className="error">
        <h3>Search Error</h3>
        <p>{error?.message || 'An error occurred'}</p>
      </div>
    );
  }

  return null;
}

Search Statistics

function SearchStats() {
  const { results } = useInstantSearch();

  if (!results) return null;

  return (
    <div>
      <p>
        {results.nbHits.toLocaleString()} results found in{' '}
        {results.processingTimeMS}ms
      </p>
    </div>
  );
}

Refresh After Update

function RefreshButton() {
  const { refresh } = useInstantSearch();
  const [isUpdating, setIsUpdating] = useState(false);

  const handleUpdate = async () => {
    setIsUpdating(true);
    try {
      // Perform your index update
      await updateAlgoliaIndex();
      
      // Refresh the search results
      refresh();
    } finally {
      setIsUpdating(false);
    }
  };

  return (
    <button onClick={handleUpdate} disabled={isUpdating}>
      {isUpdating ? 'Updating...' : 'Update Index'}
    </button>
  );
}

Multi-Index Results

function MultiIndexStats() {
  const { scopedResults } = useInstantSearch();

  return (
    <div>
      {scopedResults.map(({ indexId, results }) => (
        <div key={indexId}>
          <h3>{indexId}</h3>
          <p>{results.nbHits} results</p>
        </div>
      ))}
    </div>
  );
}

Custom Middleware

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

function InsightsSetup() {
  const { addMiddlewares } = useInstantSearch();

  useEffect(() => {
    const insightsMiddleware = createInsightsMiddleware({
      insightsClient: window.aa,
    });

    const removeMiddlewares = addMiddlewares(insightsMiddleware);

    return removeMiddlewares;
  }, [addMiddlewares]);

  return null;
}

TypeScript

import { useInstantSearch } from 'react-instantsearch';
import type { UiState } from 'instantsearch.js';

interface MyUiState extends UiState {
  products: {
    query?: string;
    refinementList?: {
      brand?: string[];
      category?: string[];
    };
  };
}

function MyComponent() {
  const { uiState, setUiState } = useInstantSearch<MyUiState>();

  // Type-safe access
  const query = uiState.products.query;
  const brands = uiState.products.refinementList?.brand;

  return <div>{/* ... */}</div>;
}

Build docs developers (and LLMs) love