Skip to main content
The useHierarchicalMenu hook provides the logic to build a custom hierarchical menu component for faceted navigation with hierarchical data.

Import

import { useHierarchicalMenu } from 'react-instantsearch';

Parameters

attributes
string[]
required
Attributes to use to generate the hierarchy of the menu.
const { items } = useHierarchicalMenu({
  attributes: [
    'hierarchicalCategories.lvl0',
    'hierarchicalCategories.lvl1',
    'hierarchicalCategories.lvl2',
  ],
});
limit
number
default:"10"
Maximum number of values to display.
const { items } = useHierarchicalMenu({
  attributes: ['category'],
  limit: 5,
});
showMore
boolean
default:"false"
Whether to display the “show more” button.
const { toggleShowMore } = useHierarchicalMenu({
  attributes: ['category'],
  showMore: true,
  showMoreLimit: 20,
});
showMoreLimit
number
default:"20"
Maximum number of values to display when showing more.
separator
string
default:">"
Separator used in the attributes to separate level values.
const { items } = useHierarchicalMenu({
  attributes: ['category'],
  separator: ' > ',
});
rootPath
string | null
Prefix path to use if the first level is not the root level.
showParentLevel
boolean
default:"true"
Show the siblings of the selected parent levels of the current refined value.
sortBy
string[] | (a, b) => number
How to sort refinements. Possible values: count|isRefined|name:asc|name:desc.
const { items } = useHierarchicalMenu({
  attributes: ['category'],
  sortBy: ['name:asc'],
});
transformItems
(items: HierarchicalMenuItem[]) => HierarchicalMenuItem[]
Function to transform the items passed to the templates.

Returns

items
HierarchicalMenuItem[]
The list of hierarchical menu items.
const { items } = useHierarchicalMenu({
  attributes: ['category'],
});
items.forEach((item) => {
  console.log(item.value);      // "Electronics"
  console.log(item.label);      // "Electronics"
  console.log(item.count);      // 142
  console.log(item.isRefined);  // true/false
  console.log(item.data);       // Nested items or null
});
refine
(value: string) => void
Function to select a menu item.
const { refine } = useHierarchicalMenu({
  attributes: ['category'],
});
refine('Electronics > Phones');
canRefine
boolean
Whether refinements can be applied.
isShowingMore
boolean
Whether “show more” is currently active.
toggleShowMore
() => void
Function to toggle between showing more/less items.
canToggleShowMore
boolean
Whether the “show more” toggle is available.
createURL
(value: string) => string
Function to create a URL for a menu item.
sendEvent
SendEventForFacet
Function to send Insights events.

Examples

Basic Hierarchical Menu

import { useHierarchicalMenu } from 'react-instantsearch';

function CategoryMenu() {
  const { items, refine } = useHierarchicalMenu({
    attributes: [
      'hierarchicalCategories.lvl0',
      'hierarchicalCategories.lvl1',
      'hierarchicalCategories.lvl2',
    ],
  });

  function renderItems(items) {
    return (
      <ul>
        {items.map((item) => (
          <li key={item.value}>
            <button
              onClick={() => refine(item.value)}
              style={{ fontWeight: item.isRefined ? 'bold' : 'normal' }}
            >
              {item.label} ({item.count})
            </button>
            {item.data && renderItems(item.data)}
          </li>
        ))}
      </ul>
    );
  }

  return (
    <div>
      <h3>Categories</h3>
      {renderItems(items)}
    </div>
  );
}

With Show More

import { useHierarchicalMenu } from 'react-instantsearch';

function ExpandableHierarchicalMenu() {
  const {
    items,
    refine,
    toggleShowMore,
    isShowingMore,
    canToggleShowMore,
  } = useHierarchicalMenu({
    attributes: ['category.lvl0', 'category.lvl1'],
    limit: 5,
    showMore: true,
    showMoreLimit: 15,
  });

  function renderItems(items) {
    return (
      <ul>
        {items.map((item) => (
          <li key={item.value}>
            <button onClick={() => refine(item.value)}>
              {item.label} ({item.count})
            </button>
            {item.data && renderItems(item.data)}
          </li>
        ))}
      </ul>
    );
  }

  return (
    <div>
      <h3>Categories</h3>
      {renderItems(items)}
      {canToggleShowMore && (
        <button onClick={toggleShowMore}>
          {isShowingMore ? 'Show less' : 'Show more'}
        </button>
      )}
    </div>
  );
}

With Expansion Icons

import { useHierarchicalMenu } from 'react-instantsearch';

function HierarchicalMenuWithIcons() {
  const { items, refine } = useHierarchicalMenu({
    attributes: ['category.lvl0', 'category.lvl1', 'category.lvl2'],
  });

  function renderItems(items) {
    return (
      <ul className="hierarchical-menu">
        {items.map((item) => (
          <li key={item.value}>
            <div className="menu-item">
              {item.data && (
                <span className="icon">
                  {item.isRefined ? '▼' : '▶'}
                </span>
              )}
              <button
                onClick={() => refine(item.value)}
                className={item.isRefined ? 'refined' : ''}
              >
                {item.label} ({item.count})
              </button>
            </div>
            {item.isRefined && item.data && renderItems(item.data)}
          </li>
        ))}
      </ul>
    );
  }

  return <div>{renderItems(items)}</div>;
}

TypeScript

import { useHierarchicalMenu } from 'react-instantsearch';
import type { UseHierarchicalMenuProps } from 'react-instantsearch';

function CategoryMenu(props: UseHierarchicalMenuProps) {
  const { items, refine } = useHierarchicalMenu(props);

  function renderItems(items: typeof items): JSX.Element {
    return (
      <ul>
        {items.map((item) => (
          <li key={item.value}>
            <button onClick={() => refine(item.value)}>
              {item.label}
            </button>
            {item.data && renderItems(item.data)}
          </li>
        ))}
      </ul>
    );
  }

  return renderItems(items);
}