API Reference / React InstantSearch / DynamicWidgets
Signature
<DynamicWidgets
  // optional parameters
  transformItems={function}
  fallbackComponent={Element}
  facets={['*']|[]}
  maxValuesPerFacet={number}
>
  {children}
</DynamicWidgets>
Import
1
import { DynamicWidgets } from 'react-instantsearch-dom';

About this widget

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.

DynamicWidgets is a widget that displays matching widgets, based on the corresponding settings of the index and may be altered by a Rule. You can configure the facet merchandising through the corresponding index setting.

Learn how to set up ordering in the facet display guide.

All matching widgets mount after the first network request completes. To avoid a second network request, facets are set to ['*'] and maxValuesPerFacet is set to 20 by default.

If this behavior isn’t what you want, it can be overridden using the facets and maxValuesPerFacet parameters.

When server-rendering, InstantSearch will render in two passes, ensuring that the refinements seen on the front-end are correct.

Requirements

You must set the attributes for faceting attributesForFaceting and configure the facet order, either using the dashboard or using attributesForFaceting and renderingContent respectively with the API.

You must use at least React InstantSearch version 6.16.0 to use DynamicWidgets.

Examples

1
2
3
4
5
6
7
<DynamicWidgets fallbackComponent={Menu}>
  <RefinementList attribute="brand" />
  <HierarchicalMenu attributes={["hierarchical.lvl0", "hierarchical.lvl1"]} />
  <Panel>
    <Menu attribute="category" />
  </Panel>
</DynamicWidgets>

Options

children
type: Element[]
Optional

The children of this component will be displayed dynamically based on the result of facetOrdering. This means that any child needs to have either the “attribute” or “attributes” prop.

1
2
3
<DynamicWidgets>
  <RefinementList attribute="brand" />
</DynamicWidgets>
fallbackComponent
type: Widget
Optional

The fallbackComponent prop is used if no widget from children matches. The component gets called with an attribute prop.

1
<DynamicWidgets fallbackComponent={RefinementList} />
transformItems
type: function
Optional

A function to transform the attributes to render, or using a different source to determine the attributes to render.

1
2
3
4
5
<DynamicWidgets
  transformItems={(items, { results }) => {
    return items;
  }},
/>
facets
type: ['*']|[]
default: ['*']
Optional

The facets to apply before dynamic widgets get mounted. Setting the value to ['*'] will request all facets and avoid an additional network request once the widgets are added.

1
2
3
4
<DynamicWidgets
  // ...
  facets={['*']}
/>
maxValuesPerFacet
type: number
default: 20
Optional

The default number of facet values to request. It’s recommended to have this value at least as high as the highest limit and showMoreLimit of dynamic widgets, as this will prevent a second network request once that widget mounts.

To avoid pinned items not showing in the result, make sure you choose a maxValuesPerFacet at least as high as all the most pinned items you have.

1
2
3
4
<DynamicWidgets
  // ...
  maxValuesPerFacet={500}
/>

Customize the UI with connectDynamicWidgets

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

// 2. Connect the component using the connector
const CustomDynamicWidgets = connectDynamicWidgets(DynamicWidgets);

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

Create a React component

const DynamicWidgets = ({
  object[] attributesToRender,
}) => {
  // return the DOM output
};

Provided Props

Rendering options

attributesToRender
type: string[]

The list of refinement values to display returned from the Algolia API.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function DynamicWidgets({
  attributesToRender,
}) {

  // on initial render this will be empty, but React InstantSearch keeps
  // search state for unmounted components in place, so routing works.
  return (
    <>
      {attributesToRender.map(attribute => (
        <RefinementList key={attribute} attribute={attribute} />
      ))}
    </>
  );
}

Create and instantiate your connected widget

const CustomDynamicWidgets = connectDynamicWidgets(DynamicWidgets);

<CustomDynamicWidgets
  // optional parameters
  transformItems={function}
/>

Exposed Props

Instance options

transformItems
type: function
Optional

A function to transform the attributes to render, or using a different source to determine the attributes to render.

1
2
3
4
5
<CustomDynamicWidgets
  transformItems={(items, { results }) => {
    return items;
  }}
/>
facets
type: ['*']|[]
default: ['*']
Optional

The facets to apply before dynamic widgets get mounted. Setting the value to ['*'] will request all facets and avoid an additional network request once the widgets are added.

1
2
3
4
<CustomDynamicWidgets
  // ...
  facets={['*']}
/>
maxValuesPerFacet
type: number
default: 20
Optional

The default number of facet values to request. It’s recommended to have this value at least as high as the highest limit and showMoreLimit of dynamic widgets, as this will prevent a second network request once that widget mounts.

To avoid pinned items not showing in the result, make sure you choose a maxValuesPerFacet at least as high as all the most pinned items you have.

1
2
3
4
<CustomDynamicWidgets
  // ...
  maxValuesPerFacet={500}
/>

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 0. Create a function to extract the attribute from a widget
function getAttribute(component) {
  if (typeof component !== 'object') {
    return undefined;
  }

  if (component.props.attribute) {
    return component.props.attribute;
  }
  if (Array.isArray(component.props.attributes)) {
    return component.props.attributes[0];
  }
  if (component.props.children) {
    return getAttribute(React.Children.only(component.props.children));
  }

  return undefined;
}

// 1. Create a render function
const RenderDynamicWidgets = ({
  attributesToRender,
  fallbackComponent: Fallback,
  children,
}) => {
  const widgets = new Map();

  // retrieve the attribute for children
  React.Children.forEach(children, (child) => {
    const attribute = getAttribute(child);
    if (!attribute) {
      throw new Error(
        `Could not find "attribute" prop for ${getDisplayName(child)}.`
      );
    }
    widgets.set(attribute, child);
  });

  // on initial render this will be empty, but React InstantSearch keeps
  // search state for unmounted components in place, so routing works.
  return (
    <>
      {attributesToRender.map((attribute) => (
        <Fragment key={attribute}>
          {widgets.get(attribute) || <Fallback attribute={attribute} />}
        </Fragment>
      ))}
    </>
  );
};

// 2. Create the custom widget
const CustomDynamicWidgets = connectDynamicWidgets(
  RenderDynamicWidgets
);

// 3. Instantiate
<CustomDynamicWidgets fallbackComponent={Menu}>
  <Panel>
    <RefinementList attribute="brand" />
  </Panel>
</CustomDynamicWidgets>;
Did you find this page helpful?