API Reference / React InstantSearch Widgets / InfiniteHits
Aug. 23, 2019

InfiniteHits

Widget signature
<InfiniteHits
  // Optional parameters
  showPrevious={boolean}
  hitComponent={function}
  translations={object}
/>

About this widget

The InfiniteHits is used to display an infinite list of results with a “Load more” button. To create an infinite scroll experience, take a look at the infinite scroll guide.

To configure the number of retrieved hits, use the HitsPerPage widget or pass the hitsPerPage prop to a Configure widget.

Examples

1
2
3
import { InfiniteHits } from 'react-instantsearch-dom';

<InfiniteHits />

Props

showPrevious
type: boolean
default: false
Optional

Enable the button to load previous results.

The button is only used if URL Sync is implemented and if the user is not on the first page. It’s possible to override this behavior by using connectors.

1
<InfiniteHits showPrevious />
hitComponent
type: function
Optional

Renders each hit from the results. If it is not provided, the rendering defaults to displaying the hit in its JSON form. The provided component is called with a hit prop.

1
2
3
const Hit = ({ hit }) => <p>{hit.name}</p>;

<InfiniteHits hitComponent={Hit} />
translations
type: object
Optional

A mapping of keys to translation values.

  • loadPrevious: label for the “Load previous” button.
  • loadMore: label for the “Load more” button.
1
2
3
4
5
6
7
<InfiniteHits
  // ...
  translations={{
    loadPrevious: "Load previous",
    loadMore: 'Load more',
  }}
/>

HTML output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="ais-InfiniteHits">
  <button class="ais-InfiniteHits-loadPrevious">
    Load previous
  </button>
  <ol class="ais-InfiniteHits-list">
    <li class="ais-InfiniteHits-item">
      ...
    </li>
    <li class="ais-InfiniteHits-item">
      ...
    </li>
    <li class="ais-InfiniteHits-item">
      ...
    </li>
  </ol>
  <button class="ais-InfiniteHits-loadMore">
    Load more
  </button>
</div>

Customize the UI - connectInfiniteHits

If you want to create your own UI of the InfiniteHits widget or use another UI library, you can use connectors.

Connectors are higher-order components. They encapsulate the logic for a specific kind of widget and they provide a way to interact with the InstantSearch context.

They have an outer component API that we call exposed props, and they provide some other props to the wrapped components which are called the provided props.

It’s a 3-step process:

// 1. Create a React component
const InfiniteHits = () => {
  // return the DOM output
};

// 2. Connect the component using the connector
const CustomInfiniteHits = connectInfiniteHits(InfiniteHits);

// 3. Use your connected widget
<CustomInfiniteHits />

Create a React component

const InfiniteHits = ({
  object[] hits,
  boolean hasPrevious,
  boolean hasMore,
  function refinePrevious,
  function refineNext,
}) => {
  // return the DOM output
};

Provided Props

hits
type: object[]

The hits that matched the search request.

1
2
3
4
5
6
7
const InfiniteHits = ({ hits }) => (
  <ol>
    {hits.map(hit => (
      <li key={hit.objectID}>{hit.name}</li>
    ))}
  </ol>
);
hasPrevious
type: boolean

Whether there are previous pages to load.

1
2
3
4
5
6
7
8
const InfiniteHits = ({ hits, hasPrevious, refinePrevious }) => (
  <div>
    <button onClick={refinePrevious} disabled={!hasPrevious}>
      Show previous
    </button>
    nbHits: {hits.length}
  </div>
);
hasMore
type: boolean

Whether there are more pages to load.

1
2
3
4
5
6
7
8
const InfiniteHits = ({ hits, hasMore, refineNext }) => (
  <div>
    nbHits: {hits.length}
    <button onClick={refineNext} disabled={!hasMore}>
      Show more
    </button>
  </div>
);
refinePrevious
type: function

Loads previous results.

1
2
3
4
5
6
7
8
9
10
const InfiniteHits = ({ hits, refinePrevious }) => (
  <div>
    <button onClick={refinePrevious}>Show previous</button>
    <ol>
      {hits.map(hit => (
        <li key={hit.objectID}>{hit.name}</li>
      ))}
    </ol>
  </div>
);
refineNext
type: function

Loads more results.

1
2
3
4
5
6
7
8
9
10
const InfiniteHits = ({ hits, refineNext }) => (
  <div>
    <ol>
      {hits.map(hit => (
        <li key={hit.objectID}>{hit.name}</li>
      ))}
    </ol>
    <button onClick={refineNext}>Show more</button>
  </div>
);

Create and instantiate your connected widget

const CustomInfiniteHits = connectInfiniteHits(InfiniteHits);

<CustomInfiniteHits />

Full example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { connectInfiniteHits } from 'react-instantsearch-dom';

const InfiniteHits = ({
  hits,
  hasPrevious,
  refinePrevious,
  hasMore,
  refineNext,
}) => (
  <div>
    <button disabled={!hasPrevious} onClick={refinePrevious}>
      Show previous
    </button>
    <ol>
      {hits.map(hit => (
        <li key={hit.objectID}>{hit.name}</li>
      ))}
    </ol>
    <button disabled={!hasMore} onClick={refineNext}>
      Show more
    </button>
  </div>
);

const CustomInfiniteHits = connectInfiniteHits(InfiniteHits);

Sending Click and Conversion events

Using the connectHitInsights connector, you can hook the Insights API client for JavaScript and use it within the context of a hit. This way, you can send click and conversion events right from the InfiniteHits widget.

Requirements

This requires installing the search-insights library separately:

You can refer to our insights documentation for more details.

It’s a 3-step process:

1. Install the Insights API client for JavaScript and enable the clickAnalytics search parameter on InstantSearch

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
  var ALGOLIA_INSIGHTS_SRC = "https://cdn.jsdelivr.net/npm/search-insights@1.3.0";

  !function(e,a,t,n,s,i,c){e.AlgoliaAnalyticsObject=s,e.aa=e.aa||function(){
  (e.aa.queue=e.aa.queue||[]).push(arguments)},i=a.createElement(t),c=a.getElementsByTagName(t)[0],
  i.async=1,i.src=ALGOLIA_INSIGHTS_SRC,c.parentNode.insertBefore(i,c)
  }(window,document,"script",0,"aa");

  aa('init', {
    appId: 'YourApplicationID',
    apiKey: 'YourSearchOnlyAPIKey',
  });
</script>
1
2
3
import { Configure } from 'react-instantsearch-dom';

<Configure clickAnalytics />

2. Connect the Insights API client for JavaScript with your Hit component.

1
2
3
4
5
6
7
8
9
10
11
12
import { connectHitInsights } from 'react-instantsearch-dom';

const Hit = ({ hit, insights }) => (
  <article>
    <h1>{hit.name}</h1>
    <button> Add to favorite </button>
  </article>
);

const HitWithInsights = connectHitInsights(window.aa)(Hit);

<InfiniteHits hitComponent={HitWithInsights} />;

3. Call the insights function from your Hit component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const Hit = ({ hit, insights }) => (
  <article>
    <h1>{hit.name}</h1>
    <button
      onClick={() =>
        insights('clickedObjectIDsAfterSearch', {
          eventName: 'Add to favorite'
        })
      }
    >
      Add to favorite
    </button>
  </article>
);

Provided props

hit
type: object

A single hit, part of the hits that matched the search request.

It is worth noting that it has the following read-only properties:

  • __queryID: the query ID (only if clickAnalytics is to true)
  • __position: the absolute position of the hit
1
2
3
4
5
6
7
8
9
const Hit = ({ hit }) => (
  <a href={`/product/${hit.objectID}?queryID=${hit.__queryID}`}>
    <article>
      <h1>
        {hit.name} at position {hit.__position}
      </h1>
    </article>
  </a>
);
insights
type: function
signature: (method: string, payload: object) => void

Sends insights events.

  • method: string: the insights method to be called. Only search-related methods are supported: 'clickedObjectIDsAfterSearch', 'convertedObjectIDsAfterSearch'.

  • payload: object: the payload to be sent.

    • eventName: string: the name of the event.
    • objectIDs?: string[]: a list of objectIDs.
    • index?: string: the name of the index related to the click.
    • queryID?: string: the Algolia queryID that can be found in the search response when using clickAnalytics: true.
    • userToken?: string: a user identifier.
    • positions?: number[]: the position of the click in the list of Algolia search results.

When not provided, objectIDs, index, queryID, and positions are inferred by the InstantSearch context and the passed hit:

  • objectIDs by default contains a single objectID: the objectID of the hit.
  • index by default is the name of index that returned the hit.
  • queryID by default is the ID of the query that returned the hit.
  • positions by default contains a single, absolute position: the position of the hit.

For more details on the constraints that apply to each payload property, please refer to insights client documentation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const Hit = ({ hit, insights }) => (
  <article>
    <h1>{hit.name}</h1>

    <button
      onClick={() =>
        insights('clickedObjectIDsAfterSearch', {
          eventName: 'Add to favorite'
        })
      }
    >
      Add to favorite
    </button>
  </article>
);

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// insights client initialized and exposed as `window.aa`
import {
  Configure,
  InfiniteHits,
  connectHitInsights
} from 'react-instantsearch-dom';

const Hit = ({ hit, insights }) => (
  <a href={`/product.html?objectID=${hit.objectID}&queryID=${hit.__queryID}`}>
    <article>
      <h1>{hit.name}</h1>

      <button
        onClick={() =>
          insights('clickedObjectIDsAfterSearch', {
            eventName: 'Add to favorite'
          })
        }
      >
        Add to favorite
      </button>

      <button
        onClick={() =>
          insights('convertedObjectIDsAfterSearch', {
            eventName: 'Add to cart'
          })
        }
      >
        Add to cart
      </button>
    </article>
  </a>
);

const HitWithInsights = connectHitInsights(window.aa)(Hit);

// usage
<Configure clickAnalytics />
<InfiniteHits hitComponent={HitWithInsights} />

Did you find this page helpful?