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;
At this point, the facets are tiles rather than checkboxes with labels, but they’re not interactive yet.
Feedback
<% elem.innerText %>