InstantSearch / React / V6 / Guides / Injecting content between hits

Inject Hits from Another Algolia Index

Deprecated content
This documentation is for a deprecated version of React InstantSearch. Some features and settings may be missing or their usage may have changed. Refer to the documentation for the latest version of React InstantSearch for up-to-date information.

Content injection consists of inserting data between search results. With React InstantSearch, you can build a custom widget to mix results from two or more indices into a single set of hits.

For example, if you’re building a search experience for ingredients, you might want to inject recipes using those ingredients. These recipes would live in a secondary index, and receive search parameters such as the query and facets.

Screenshot showing content from another Algolia index injected between regular hits

Requirements

React InstantSearch exposes a connector API that lets you reuse existing logic and plug your own. With it, you can build a custom React InstantSearch widget to mix regular Algolia results with injected content. Make sure you’re familiar with this concept before continuing to the next section.

Set up indices

To find related recipes when searching for ingredients, they need to match the same queries.

For example, in your “ingredients” records, you can use a unique name to identify each ingredient. Then, you can use the same name in the list of ingredients for each recipe in the “recipes” index.

1
2
3
4
5
6
7
8
[
  {
    "ingredient": "sesame seeds",
    "title": "Sesame",
    "summary": "Sesame is a flowering plant in the genus Sesamum, also called benne..."
  },
  // ...
]

Make sure you declare any attribute you with to search into as searchableAttributes.

Inject custom content between hits

To mix hits from the two indices, you first need to make sure to register them all by mounting an index-widget widget. You can use a nested configure widget to define what search parameters to use and what to inherit from the parent index.

In the following example, the index “recipes” always returns a single index from the first page, but receives the query, the facets, and any other parameter defined higher in the component tree.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
import {
  InstantSearch,
  Configure,
  Index,
  SearchBox,
} from 'react-instantsearch-dom';

function App() {
  return (
    <InstantSearch searchClient={searchClient} indexName="ingredients">
      <Configure hitsPerPage={8} />
      <Index indexName="recipes">
        <Configure hitsPerPage={1} page={0} />
      </Index>
      <SearchBox />
    </InstantSearch>
  );
}

Then, you can display results from “ingredients” and inject results from “recipes”. In the following example, there’s a slot that injects hits from the “recipes” index in position 3.

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
41
42
43
import React from 'react';
import {
  InstantSearch,
  Configure,
  Index,
  SearchBox,
} from 'react-instantsearch-dom';

import { InjectedHits } from './InjectedHits';

function App() {
  return (
    <InstantSearch searchClient={searchClient} indexName="ingredients">
      <Configure hitsPerPage={8} />
      <Index indexName="recipes">
        <Configure hitsPerPage={1} page={0} />
      </Index>
      <SearchBox />
      <InjectedHits
        slots={() => [
          {
            injectAt: 3,
            getHits: ({ resultsByIndex }) => resultsByIndex.recipes?.hits || [],
            slotComponent: RecipeHit,
          },
        ]}
        hitComponent={IngredientHit}
      />
    </InstantSearch>
  );
}

function RecipeHit() {
  return (
    {/* ... */}
  );
}

function IngredientHit() {
  return (
    {/* ... */}
  );
}

Regular hits from “ingredients” use the component defined with hitComponent, while injected hits use the slotComponent.

Dynamic positioning with hits

Instead of passing a static position to injectAt, you can store a dynamic position in hits, along with their data, and use it in the code.

If you inject multiple slots at the same position, they’re injected in the defined slot order.

1
2
3
4
5
6
7
8
9
[
  {
    "position": 3,
    "title": "Butter chicken",
    "ingredients": [
      // ...
    ]
  }
]
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
import React from 'react';
import {
  InstantSearch,
  Configure,
  Index,
  SearchBox,
} from 'react-instantsearch-dom';

import { InjectedHits } from './InjectedHits';

function App() {
  return (
    <InstantSearch searchClient={searchClient} indexName="ingredients">
      <Configure hitsPerPage={8} />
      <Index indexName="recipes">
        <Configure hitsPerPage={1} page={0} />
      </Index>
      <SearchBox />
      <InjectedHits
        slots={({ resultsByIndex }) => {
          const [recipe] = resultsByIndex.recipes?.hits || [];

          return [
            {
              injectAt: recipe.position,
              getHits: () => [recipe].filter(Boolean),
              slotComponent: RecipeHit,
            },
          ];
        }}
        hitComponent={IngredientHit}
      />
    </InstantSearch>
  );
}

// ...
Did you find this page helpful?