API Reference / React InstantSearch / RefinementList
Signature
<RefinementList
  attribute={string}
  // Optional parameters
  defaultRefinement={string[]}
  facetOrdering={boolean}
  operator={string}
  limit={number}
  showMore={boolean}
  showMoreLimit={number}
  searchable={boolean}
  transformItems={function}
  translations={object}
/>

About this widget # A

We released React InstantSearch Hooks, a new InstantSearch library for React. We recommend using React InstantSearch Hooks in new projects or upgrading from React InstantSearch.

The RefinementList widget is one of the most common widgets that you can find in a search UI. With this widget, the user can filter the dataset based on facet values.

The widget only displays the most relevant facet values for the current search context.

This widget also implements search for facet values, which is a mini search inside the values of the facets. This makes it easy to deal with uncommon facet values.

Requirements#

The attribute provided to the widget must be added in attributes for faceting, either on the dashboard or using attributesForFaceting with the API.

If you are using the searchable prop, you also need to make the attribute searchable using the dashboard or using the searchable modifier of attributesForFaceting with the API.

Examples # A

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

<RefinementList attribute="brand" />

Props # A

attribute #
type: string
Required

The name of the attribute in the record.

1
<RefinementList attribute="brand" />
defaultRefinement #
type: string[]
Optional

The value of the item selected by default.

1
2
3
4
<RefinementList
  // ...
  defaultRefinement={['Apple']}
/>
facetOrdering #
type: boolean
default: true
Optional

Apply the rules of renderingContent.facetOrdering for this widget.

1
2
3
4
<RefinementList
  // ...
  facetOrdering
/>
operator #
type: string ("or"|"and")
default: or
Optional

How to apply the refinements.

1
2
3
4
<RefinementList
  // ...
  operator="and"
/>
limit #
type: number
default: 10
Optional

How many facet values to retrieve. When you enable the showMore feature, this is the number of facet values to display before clicking the “Show more” button.

1
2
3
4
<RefinementList
  // ...
  limit={20}
/>
showMore #
type: boolean
default: false
Optional

Whether to display a button that expands the number of items.

1
2
3
4
<RefinementList
  // ...
  showMore
/>
showMoreLimit #
type: number
default: 20
Optional

The maximum number of displayed items. Only used when showMore is set to true.

1
2
3
4
<RefinementList
  // ...
  showMoreLimit={30}
/>
searchable #
type: boolean
Optional

Whether to add a search input to let the user search for more facet values.

To make this feature work, you need to make the attribute searchable using the dashboard or using the searchable modifier of attributesForFaceting with the API.

Note that this feature is not available if you’re using Multi Index Search.

1
2
3
4
<RefinementList
  // ...
  searchable
/>
transformItems #
type: function
Optional

Modifies the items being displayed, for example, to filter or sort them. It takes items as argument and expects them back in return.

1
2
3
4
5
6
7
8
9
<RefinementList
  // ...
  transformItems={items =>
    items.map(item => ({
      ...item,
      label: item.label.toUpperCase(),
    }))
  }
/>
translations #
type: object
Optional

A mapping of keys to translation values.

  • showMore: the label of the “Show more” button. Accepts one boolean parameter that is true if the values are expanded, false otherwise.
  • noResults: the label of the no results text when no search for facet values results are found.
  • submitTitle: the alternative text of the submit icon.
  • resetTitle: the alternative text of the reset button icon.
  • placeholder: the label of the input placeholder.
1
2
3
4
5
6
7
8
9
10
11
12
<RefinementList
  // ...
  translations={{
    showMore(expanded) {
      return expanded ? 'Show less' : 'Show more';
    },
    noResults: 'No results',
    submitTitle: 'Submit your search query.',
    resetTitle: 'Clear your search query.',
    placeholder: 'Search here...',
  }}
/>

HTML output# A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div class="ais-RefinementList">
  <div class="ais-RefinementList-searchBox">
    <!-- SearchBox widget here -->
  </div>
  <ul class="ais-RefinementList-list">
    <li class="ais-RefinementList-item ais-RefinementList-item--selected">
      <label class="ais-RefinementList-label">
        <input class="ais-RefinementList-checkbox" type="checkbox" value="Insignia™" checked="" />
        <span class="ais-RefinementList-labelText">Insignia™</span>
        <span class="ais-RefinementList-count">746</span>
      </label>
    </li>
    <li class="ais-RefinementList-item">
      <label class="ais-RefinementList-label">
        <input class="ais-RefinementList-checkbox" type="checkbox" value="Samsung">
        <span class="ais-RefinementList-labelText">Samsung</span>
        <span class="ais-RefinementList-count">633</span>
      </label>
    </li>
  </ul>
  <button class="ais-RefinementList-showMore">Show more</button>
</div>

Customize the UI with connectRefinementList# A

If you want to create your own UI of the RefinementList 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 RefinementList = () => {
  // return the DOM output
};

// 2. Connect the component using the connector
const CustomRefinementList = connectRefinementList(RefinementList);

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

Create a React component#

const RefinementList = ({
  object[] items,
  string[] currentRefinement,
  function refine,
  boolean isFromSearch,
  function searchForItems,
  function createURL,
}) => {
  // return the DOM output
};

Provided Props#

items #
type: object[]

The list of items the widget can display, with each item:

  • label: string: the label for the display of the refinement.
  • value: string[]: the values attached to this refinement.
  • count: number: the number of results that match the refinement.
  • isRefined: boolean: whether the value is selected.
1
2
3
4
5
6
7
8
9
10
11
const RefinementList = ({ items }) => (
  <ul>
    {items.map(item => (
      <li key={item.label}>
        <a href="#" style={{ fontWeight: item.isRefined ? 'bold' : '' }}>
          {item.label} ({item.count})
        </a>
      </li>
    ))}
  </ul>
);
currentRefinement #
type: string[]

The currently applied refinement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const RefinementList = ({ items, currentRefinement, refine }) => (
  <div>
    <div>Current refinement: {currentRefinement.join(', ')}</div>
    <ul>
      {items.map(item => (
        <li key={item.label}>
          <a
            href="#"
            style={{ fontWeight: item.isRefined ? 'bold' : '' }}
            onClick={event => {
              event.preventDefault();
              refine(item.value);
            }}
          >
            {item.label} ({item.count})
          </a>
        </li>
      ))}
    </ul>
  </div>
);
refine #
type: function

Toggles a refinement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const RefinementList = ({ items, refine }) => (
  <ul>
    {items.map(item => (
      <li key={item.label}>
        <a
          href="#"
          style={{ fontWeight: item.isRefined ? 'bold' : '' }}
          onClick={event => {
            event.preventDefault();
            refine(item.value);
          }}
        >
          {item.label} ({item.count})
        </a>
      </li>
    ))}
  </ul>
);
isFromSearch #
type: boolean

Whether the provided items contain facet values from the global search or from the search inside items.

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
const RefinementList = ({ items, isFromSearch, refine, searchForItems }) => (
  <ul>
    <li>
      <input
        type="search"
        onChange={event => searchForItems(event.currentTarget.value)}
      />
    </li>
    {items.map(item => (
      <li key={item.label}>
        <a
          href="#"
          style={{ fontWeight: item.isRefined ? 'bold' : '' }}
          onClick={event => {
            event.preventDefault();
            refine(item.value);
          }}
        >
          {isFromSearch ? (
            <Highlight attribute="label" hit={item} />
          ) : (
            item.label
          )}{' '}
          ({item.count})
        </a>
      </li>
    ))}
  </ul>
);
searchForItems #
type: function

Triggers a search inside items values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const RefinementList = ({ items, refine, searchForItems }) => (
  <ul>
    <li>
      <input
        type="search"
        onChange={event => searchForItems(event.currentTarget.value)}
      />
    </li>
    {items.map(item => (
      <li key={item.label}>
        <a
          href="#"
          style={{ fontWeight: item.isRefined ? 'bold' : '' }}
          onClick={event => {
            event.preventDefault();
            refine(item.value);
          }}
        >
          {item.label} ({item.count})
        </a>
      </li>
    ))}
  </ul>
);
createURL #
type: function

Generates a URL for the corresponding search state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const RefinementList = ({ items, createURL }) => (
  <ul>
    {items.map(item => (
      <li key={item.label}>
        <a
          href={createURL(item.value)}
          style={{ fontWeight: item.isRefined ? 'bold' : '' }}
        >
          {item.label} ({item.count})
        </a>
      </li>
    ))}
  </ul>
);

Create and instantiate your connected widget#

const CustomRefinementList = connectRefinementList(RefinementList);

<CustomRefinementList
  attribute={string}
  // optional parameters
  defaultRefinement={string[]}
  facetOrdering={boolean}
  operator={string}
  limit={number}
  showMore={boolean}
  showMoreLimit={number}
  searchable={boolean}
  transformItems={function}
/>

Exposed Props#

attribute #
type: string
Required

The name of the attribute in the record.

1
<CustomRefinementList attribute="brand" />
defaultRefinement #
type: string[]
Optional

The value of the item selected by default.

1
2
3
4
<CustomRefinementList
  // ...
  defaultRefinement={['Apple']}
/>
facetOrdering #
type: boolean
default: true
Optional

Apply the rules of renderingContent.facetOrdering for this widget.

1
2
3
4
<CustomRefinementList
  // ...
  facetOrdering
/>
operator #
type: string ("or"|"and")
default: or
Optional

How to apply the refinements.

1
2
3
4
<CustomRefinementList
  // ...
  operator="and"
/>
limit #
type: number
default: 10
Optional

How many facet values to retrieve. When you enable the showMore feature, this is the number of facet values to display before clicking the “Show more” button.

1
2
3
4
<CustomRefinementList
  // ...
  limit={20}
/>
showMore #
type: boolean
default: false
Optional

We don’t expose the function to toggle the number of value displayed by the widget with the connector. Yet, the option is required to enable the “Show more” behavior. The option drives how many values are retrieved (either limit or showMoreLimit).

1
2
3
4
<CustomRefinementList
  // ...
  showMore
/>
showMoreLimit #
type: number
default: 20
Optional

The maximum number of displayed items. Only used when showMore is set to true.

1
2
3
4
<CustomRefinementList
  // ...
  showMoreLimit={30}
/>
searchable #
type: boolean
Optional

With the connector, it’s your responsability to render the SearchBox and trigger the search inside items. You have to provide the option, because the connector does an extra check to verify that you are in the right context to use the searchable feature.

To make this feature work, you need to make the attribute searchable using the dashboard or using the searchable modifier of attributesForFaceting with the API.

1
2
3
4
<CustomRefinementList
  // ...
  searchable
/>
transformItems #
type: function
Optional

Modifies the items being displayed, for example, to filter or sort them. It takes items as argument and expects them back in return.

1
2
3
4
5
6
7
8
9
<CustomRefinementList
  // ...
  transformItems={items =>
    items.map(item => ({
      ...item,
      label: item.label.toUpperCase(),
    }))
  }
/>

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { Highlight, connectRefinementList } from 'react-instantsearch-dom';

const RefinementList = ({
  items,
  isFromSearch,
  refine,
  searchForItems,
  createURL,
}) => (
  <ul>
    <li>
      <input
        type="search"
        onChange={event => searchForItems(event.currentTarget.value)}
      />
    </li>
    {items.map(item => (
      <li key={item.label}>
        <a
          href={createURL(item.value)}
          style={{ fontWeight: item.isRefined ? 'bold' : '' }}
          onClick={event => {
            event.preventDefault();
            refine(item.value);
          }}
        >
          {isFromSearch ? (
            <Highlight attribute="label" hit={item} />
          ) : (
            item.label
          )}{' '}
          ({item.count})
        </a>
      </li>
    ))}
  </ul>
);

const CustomRefinementList = connectRefinementList(RefinementList);
Did you find this page helpful?