Step 1: Extracting a Facet from the Search State

When a Vertical Search API request is made, facets for the given vertical are returned. Behind the scenes, these are stored in the search state. The useSearchState hook can be used to extract a specific facet from the search state for use in a custom component.

This example defines a functional component called TileFacet that pulls out a specific facet from the search state based on its fieldId and displays the different options for the facet.

// src/components/TileFacet.tsx

import { useSearchState } from "@yext/search-headless-react";

interface TileFacetProps {
  fieldId: string;
  displayName?: string;
}

const TileFacet = ({
  fieldId,
  displayName,
}: TileFacetProps): JSX.Element | null => {
  const facet = useSearchState((state) =>
    state.filters.facets?.find((f) => f.fieldId === fieldId)
  );

  // component returns null if the facet isn't found in the search state or has no options for a partiaular set of results
  return facet && facet.options.length > 0 ? (
    <div className="mb-4">
      <span className="font-bold">{displayName ?? facet.displayName}</span>
      <div className="w-72 mt-6 flex flex-wrap">
        {facet.options.map((o, i) => (
          <div
            key={`${fieldId}_${i}`}
            className="mr-3 mb-3 border border-toast-orange md:hover:bg-[#FFB563]"
          >
            <div className="px-3 text-sm inline-block">
              {/* Each facet option contains a display name and count */}
              <span className="mr-0.5">{o.displayName}</span>
              <span className="text-xs">{`(${o.count})`}</span>
            </div>
          </div>
        ))}
      </div>
    </div>
  ) : null;
};

export default TileFacet;

Facets are usually placed next to search results like below.

// src/App.tsx

import { Pagination, SearchBar, VerticalResults } from "@yext/search-ui-react";
import BeverageCard from "./components/cards/BeverageCard";
import TileFacet from "./components/TileFacet";

const App = (): JSX.Element => {
  return (
    <div className="flex justify-center px-4 py-6">
      <div className="w-full max-w-5xl">
        <SearchBar />
        <div className="flex">
          <div>
            <TileFacet fieldId="c_usState" displayName="State" />
            <TileFacet fieldId="c_originCountry" displayName="Country" />
          </div>
          <VerticalResults
            customCssClasses={{
              verticalResultsContainer:
                "grid md:grid-cols-2 lg:grid-cols-3 gap-4 grid-cols-1",
            }}
            CardComponent={BeverageCard}
          />
        </div>
        <Pagination />
      </div>
    </div>
  );
};

export default App;

custom_facet

At this point, the facets are tiles rather than checkboxes with labels, but they’re not interactive yet.

Feedback