> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# middleware

> Adds custom logic to your React InstantSearch apps.

<Note>
  This is the **React InstantSearch v7** documentation.
  If you're upgrading from v6, see the [upgrade guide](/doc/guides/building-search-ui/upgrade-guides/react/#migrate-from-react-instantsearch-v6-to-react-instantsearch-v7).
  If you were using React InstantSearch Hooks,
  this v7 documentation applies—just check for [necessary changes](/doc/guides/building-search-ui/upgrade-guides/react/#migrate-from-react-instantsearch-hooks-to-react-instantsearch-v7).
  To continue using v6, you can find the [archived documentation](https://algolia.com/old-docs/deprecated/instantsearch/react/v6/api-reference/instantsearch/).
</Note>

```js Signature theme={"system"}
function middleware({ instantSearchInstance }) {
  return {
    onStateChange({ uiState }) {},
    subscribe() {},
    unsubscribe() {},
  };
}
```

## About this widget

The `middleware` function returns an object with [`onStateChange`](#param-on-state-change),
[`subscribe`](#param-subscribe),
and [`unsubscribe`](#param-unsubscribe) functions.

The `middleware` function doesn't perform any actions itself but lets you inject logic into InstantSearch.js,
for example, [sending events to Google Analytics](/doc/guides/building-search-ui/going-further/integrate-google-analytics/react).
To [send Algolia click and conversion events](/doc/guides/building-search-ui/events/react),
use the [`insights`](/doc/api-reference/widgets/insights/react) middleware.

### Requirements

* [InstantSearch.js](https://github.com/algolia/instantsearch) v4.8.3 or later.

## Examples

```jsx JavaScript icon=code theme={"system"}
function middleware({ instantSearchInstance }) {
  return {
    onStateChange({ uiState }) {
      // Do something with `uiState` every time the state changes.
    },
    subscribe() {
      // Do something when the InstantSearch instance starts.
    },
    unsubscribe() {
      // Do something when the InstantSearch instance is disposed of.
    },
  };
}

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

  React.useLayoutEffect(() => {
    return addMiddlewares(middleware);
  }, [addMiddlewares]);
}

function App() {
  return (
    <InstantSearch searchClient={searchClient} indexName="instant_search">
      <Middleware />
    </InstantSearch>
  );
}
```

## Options

<ParamField body="instantSearchInstance" type="object" required>
  You have access to the instance of [`instantsearch`](/doc/api-reference/widgets/instantsearch/js)
  which lets you read values from the instance or call instance methods like `addWidgets`, `setUiState`, and `refresh`.

  ```js JavaScript icon=code theme={"system"}
  function middleware({ instantSearchInstance }) {
    return {
      onStateChange({ uiState }) {
        // ...
      },
      subscribe() {
        // ...
      },
      unsubscribe() {
        // ...
      },
    };
  }
  ```
</ParamField>

## Hooks

<ParamField body="onStateChange" type="({ uiState }) => void" required>
  The function is called with [`uiState`](/doc/api-reference/widgets/ui-state/js) whenever the state changes.

  ```js JavaScript icon=code theme={"system"}
  function middleware({ instantSearchInstance }) {
    return {
      // ...
      onStateChange({ uiState }) {
        const indexName = "<your-index-name>";
        const { query } = uiState[indexName];
        const title = document.querySelector("<your-selector>");
        title.innerText = query ? `Query: ${query}` : `No query`;
      },
    };
  }
  ```
</ParamField>

<ParamField body="subscribe" type="() => void" required>
  This function is called when the InstantSearch instance starts (when `search.start` is called).
  This is where you can add event listeners, subscribe to an API, and run any side effects.

  ```js JavaScript icon=code theme={"system"}
  function middleware({ instantSearchInstance }) {
    let subscription;
    let listener;

    return {
      // ...
      subscribe() {
        subscription = someAPI.subscribe();

        listener = (event) => {
          // do something
        };
        document
          .querySelector("<your-selector>")
          .addEventListener("click", listener);
      },
    };
  }
  ```
</ParamField>

<ParamField body="unsubscribe" type="() => void" required>
  The function is called when the InstantSearch instance is disposed of.
  You can clean up anything you initiated in the `subscribe` function.

  ```js JavaScript icon=code theme={"system"}
  function middleware({ instantSearchInstance }) {
    let subscription;
    let listener;

    return {
      // ...
      unsubscribe() {
        subscription.unsubscribe();

        document
          .querySelector("<your-selector>")
          .removeEventListener("click", listener);
      },
    };
  }
  ```
</ParamField>
