Step 1: Basic Navigation
Install React Router
There are a few different options for adding routing to a React application, but this guide will utilize React Router. Add it with NPM or Yarn:
NPM
npm install react-router-dom
Yarn
yarn add react-router-dom
Universal and Vertical Result Pages
Before you add routing to your application, you’ll add a generic page for both Universal and Vertical Results. In a new folder called pages
, add a file called VerticalResultsPage.tsx
. When this component is rendered, the Search Headless useSearchActions
will set the vertical and execute a vertical query.
// src/pages/VerticalResultsPage.tsx
import { useSearchActions } from "@yext/search-headless-react";
import { StandardCard, VerticalResults } from "@yext/search-ui-react";
import { useEffect } from "react";
interface VerticalResultsPageProps {
verticalKey: string;
}
export const VerticalResultsPage = ({
verticalKey,
}: VerticalResultsPageProps): JSX.Element => {
const searchActions = useSearchActions();
useEffect(() => {
searchActions.setVertical(verticalKey);
searchActions.executeVerticalQuery();
}, [verticalKey, searchActions]);
return <VerticalResults CardComponent={StandardCard} />;
};
Create a component called UniversalResultsPage.tsx
. Here, setUniversal
is called to clear the vertical key before executeUniversalQuery
is called. universalResultsConfig
is used to create a label for each vertical in the <UniveralResults/>
.
// src/pages/UniversalResultsPage.tsx
import { useSearchActions } from "@yext/search-headless-react";
import { UniversalResults, VerticalConfigMap } from "@yext/search-ui-react";
import { useEffect } from "react";
const universalResultsConfig: VerticalConfigMap = {
events: {
label: "Events",
},
locations: {
label: "Locations",
},
artists: {
label: "Artists",
},
};
export const UniversalResultsPage = (): JSX.Element => {
const searchActions = useSearchActions();
useEffect(() => {
searchActions.setUniversal();
searchActions.executeUniversalQuery();
}, [searchActions]);
return <UniversalResults verticalConfigMap={universalResultsConfig} />;
};
The last file you’ll add to your pages folder is StandardLayout.tsx
. This defines a simple layout for each search page where the SearchBar
appears above the search results.
// src/pages/StandardLayout.tsx
import { SearchBar } from "@yext/search-ui-react";
export interface StandardLayoutProps {
page: JSX.Element;
}
export const StandardLayout = ({ page }: StandardLayoutProps): JSX.Element => {
return (
<>
<SearchBar />
{page}
</>
);
};
Adding a PageRouter
You need to be able to navigate to the different pages you just created so create a file called PageRouter.tsx
where you’ll import BrowserRouter
. Any routes defined within the BrowserRouter
will be able to use any of the the components and hooks from React Router. Within BrowswerRouter
, the Routes
component contains each Route
you define in routeConfig
. You can learn more about BrowserRouter
here
and Routes
/Route
here
.
// src/PageRouter.tsx
import { Route, Routes, BrowserRouter } from "react-router-dom";
import { StandardLayout } from "./pages/StandardLayout";
import { UniversalResultsPage } from "./pages/UniversalResultsPage";
import { VerticalResultsPage } from "./pages/VerticalResultsPage";
export const routeConfig: {
label: string,
path: string,
element: JSX.Element,
}[] = [
{
label: "All",
path: "/",
element: <StandardLayout page={<UniversalResultsPage />} />,
},
{
label: "Events",
path: "/events",
element: (
<StandardLayout page={<VerticalResultsPage verticalKey="events" />} />
),
},
{
label: "Locations",
path: "/locations",
element: (
<StandardLayout page={<VerticalResultsPage verticalKey="locations" />} />
),
},
{
label: "Artists",
path: "/artists",
element: (
<StandardLayout page={<VerticalResultsPage verticalKey="artists" />} />
),
},
];
export const PageRouter = () => {
return (
<BrowserRouter>
<Routes>
{routeConfig.map((route) => (
<Route key={route.path} path={route.path} element={route.element} />
))}
</Routes>
</BrowserRouter>
);
};
Add PageRouter
to App.tsx
. After you add it, run your app locally. If you visit
localhost:3000/locations
in your browser, you should see a Vertical Query network request in your browser developer tools with the vertical key set to “locations” and the query set to whatever is in your SearchBar
.
// src/App.tsx
import { PageRouter } from "./PageRouter";
const App = (): JSX.Element => {
return (
<div className="flex justify-center px-4 py-6">
<div className="w-full max-w-5xl">
<PageRouter />
</div>
</div>
);
};
export default App;
Navigating Between Verticals
You can’t expect for users to have to manually change the URL to search different verticals so you’ll need to add a NavBar
component. NavBar
will use the Link
component from React Router to navigate between the different pages in our application that are defined in routeConfig
. You can learn more about Link
here
.
// src/components/NavBar.tsx
import { Link } from "react-router-dom";
import { routeConfig } from "../PageRouter";
import classNames from "classnames";
import { useSearchState } from "@yext/search-headless-react";
export const NavBar = (): JSX.Element => {
const currentVertical = useSearchState((state) => state.vertical.verticalKey);
const isActiveLink = (path: string) =>
path.replace("/", "") === currentVertical ||
(path === "/" && currentVertical === undefined);
const renderLink = (label: string, path: string): JSX.Element => {
return (
<Link key={`${path}_link`} to={path}>
<div
className={classNames(
"whitespace-nowrap py-3 mt-1 font-medium text-md border-b-2 hover:border-gray-300 border-transparent",
{
"text-blue-600 border-blue-600": isActiveLink(path),
}
)}
>
<div className="py-3 px-2">{label}</div>
</div>
</Link>
);
};
return (
<nav className="border-b border-gray-200 text-gray-600 flex space-x-6 font-medium mb-6">
{routeConfig.map((route) => renderLink(route.label, route.path))}
</nav>
);
};
Add the NavBar
to StandardLayout
so that it appears below the SearchBar
on every page.
// src/pages/StandardLayout.tsx
import { SearchBar } from "@yext/search-ui-react";
import { NavBar } from "../components/NavBar";
export interface StandardLayoutProps {
page: JSX.Element;
}
export const StandardLayout = ({ page }: StandardLayoutProps): JSX.Element => {
return (
<>
<SearchBar />
<NavBar />
{page}
</>
);
};
Now, you should be able to easily navigate between Universal Search and the different verticals in your search experience.