Step 1: Basic Navigation

light bulb
Note
This guide uses React Router v6 which has a few differences from older versions of React Router. You can check out this page to learn about how to upgrade to v6 . However, the concepts covered in this guide will still apply to older versions.

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

CopyCopied!
npm install react-router-dom

Yarn

CopyCopied!
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.

CopyCopied!
// 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/>.

CopyCopied!
// 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.

CopyCopied!
// 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 .

CopyCopied!
// 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.

CopyCopied!
// 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;

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 .

CopyCopied!
// 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.

CopyCopied!
// 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.

nav_between_verts