Step 2: Manage Sort in the Headless State

In the functional component, useSearchState is used to get the list of sorts being applied to the vertical results. This component will designed to only allow one sort to be set at any given time.

selectedSort will exist if items in sortByOptions matches up with the first item in the sortBys list.

Since the <VerticalResults /> component will show all results for a vertical if none are returned by the query, both state.vertical.resultsCount and state.vertical.noResults?.allResultsForVertical.resultsCount need to be checked. The component will return null if there are no results for either.

// src/components/SortDropdown.tsx

import {
  Direction,
  SortBy,
  SortType,
  useSearchActions,
  useSearchState,
} from "@yext/search-headless-react";
import { useState } from "react";

// object that has a label for the different sort types
const sortByOptions: { label: string, sortBy: SortBy }[] = [
  {
    label: "Name: A-Z",
    sortBy: {
      field: "name",
      direction: Direction.Ascending,
      type: SortType.Field,
    },
  },
  {
    label: "Name: Z-A",
    sortBy: {
      field: "name",
      direction: Direction.Descending,
      type: SortType.Field,
    },
  },
];

const SortingDrawer = (): JSX.Element | null => {
  // sortBys contains all the sortBy options that are in the search state
  const sortBys: SortBy[] | undefined = useSearchState(
    (state) => state.vertical.sortBys
  );
  // checking both result counts as <VerticalResults /> will show allResultsForVertical if there are no results for query
  const resultsCount =
    useSearchState(
      (state) =>
        state.vertical.resultsCount ||
        state.vertical.noResults?.allResultsForVertical.resultsCount
    ) ?? 0;

  const searchActions = useSearchActions();

  // selectedSort is the currently selected sortBy option
  const selectedSort = sortByOptions.find(
    (s) =>
      s.sortBy.field === sortBys?.[0]?.field &&
      s.sortBy.direction === sortBys?.[0]?.direction
  );

  return resultsCount ? <></> : null;
};