Article image

Creating a Search Page using Algolia React InstantSearch with Next.js


Algolia is a search engine that delivers real-time results and allows you to quickly implement search for your application. This article will walk through creating a simple search page (similar to ours) using Algolia’s React InstantSearch library. 

Setting Up Your Index

Creating Your Index

  • Go to your Algolia dashboard and click “Create Application”. Choose a location for your server and click “Create”. 
  • Choose a name for your new index. 

Importing Your Data 

There are multiple options for getting your data into your index. This guide will go over using the Algolia API.

  • Install Algolia instantsearch with npm install algoliasearch react-instantsearch
  • Create a new route.ts file under a path of your choice in the app directory (for example, app/lookup/route.ts).
  • Initialize your Algolia client and write a GET request handler that posts your data to Algolia 
    • You can find your API keys under “API keys” tab of your project. You can use the default keys, but you might want to create your own - one with search permissions to use with your search page and one with posting permissions to use for your API endpoint
import { NextRequest, NextResponse } from 'next/server';


// projectKey is your ApplicationID, postKey is an API key with  
const algoliaClient = algoliasearch(projectKey, postKey );

const index = algoliaClient.initIndex('your_index_name');
export async function GET() {
  const pages = await makeSearchResultsObject(); // return an array that contains an object with info you want displayed in your search results (i.e. [{title, description, url}, …])
  index.replaceAllObjects(pages, { autoGenerateObjectIDIfNotExist: true });  // Replace all of the objects in the index with what you returned and generate an ID
  return NextResponse.json(  // optional: return your object in response
    {
      pages,
    },
    {
      status: 200,
    }
  );
}

You can manually send a request to your API endpoint when you want to update your index or set up a Vercel CRON job to periodically query it. You might also want to add an authorization key to your request and check for it within the handler or limit the amount of API calls per hour of your postKey

Creating a Search Page 

  • Start by creating a new page.tsx at the route you want your search page to be located (for example, app/search/page.tsx
  • Create and export your new search component - here we called it Search 
  • Import and use InstantSearch, SearchBox, and Hits from react-instantsearch.
'use client';

import algoliasearch from 'algoliasearch';
import { InstantSearch, SearchBox, Hits } from 'react-instantsearch';

const algoliaClient = algoliasearch(
  YOUR_APPLICATION_KEY,
  YOUR_SEARCH_KEY
);

const SearchTemplate: React.FC<{}> = () => (
  <div className="pt-20">
    <InstantSearch
      searchClient={algoliaClient}
      indexName="arkane_website_index"
    >
      <div id="search">
        <div>
          <p>Searching for</p>
          <SearchBox searchAsYouType={false} />
        </div>
        <Hits />
      </div>
    </InstantSearch>
  </div>
);

export default SearchTemplate;

Customizing Your Hit Components 

If you don’t like the look of Algolia’s default Hit components, you can add your own styling by overriding it.

'use client';

import algoliasearch from 'algoliasearch';
import { InstantSearch, SearchBox, Hits } from 'react-instantsearch';

const algoliaClient = algoliasearch(
  YOUR_APPLICATION_KEY,
  YOUR_SEARCH_KEY
);

// override Hit component
function Hit({ hit }: { hit: HitType }) {
  return (
    <div>
      <div>
        <h2>
          {hit.title}
        </h2>
        <div>
          <p>{hit.description}</p>
        </div>
        <p>{hit.location}</p>
      </div>
    </div>
  );
}

const SearchTemplate: React.FC<{}> = () => (
  <div className="pt-20">
    <InstantSearch
      searchClient={algoliaClient}
      indexName="arkane_website_index"
    >
      <div id="search">
        <div>
          <p>Searching for</p>
          <SearchBox searchAsYouType={false} />
        </div>
        <Hits hitComponent={Hit} /> {/* insert your component here */}
      </div>
    </InstantSearch>
  </div>
);

export default SearchTemplate;

Limiting Results and Using Pagination 

If you have a lot of hits and don’t want to display them all on one page, you can use pagination instead. 

...
import { InstantSearch, SearchBox, Hits, Pagination, Configure } from 'react-instantsearch'; // import Pagination and Configure

...

const SearchTemplate: React.FC<{}> = () => (
  <div className="pt-20">
    <InstantSearch
      searchClient={algoliaClient}
      indexName="arkane_website_index"
    >
      <Configure hitsPerPage={7} /> {/* adjust how many results to display per page */}
      <div id="search">
        <div>
          <p>Searching for</p>
          <SearchBox searchAsYouType={false} />
        </div>
        <Hits hitComponent={Hit} /> 
      </div>
      <Pagination /> {/*add Pagination */}
    </InstantSearch>
  </div>
);

export default SearchTemplate;

Displaying Search Statistics 

Algolia also has a built-in component that can display statistics about a query. It displays the number of hits and time to retrieve results by default. 

...
import { InstantSearch, SearchBox, Hits, Pagination, Configure, Stats } from 'react-instantsearch'; // add Stats import 
...

const SearchTemplate: React.FC<{}> = () => (
  <div className="pt-20">
    <InstantSearch
      searchClient={algoliaClient}
      indexName="arkane_website_index"
    >
      <Configure hitsPerPage={7} />       
        <div id="search">
           <Stats /> {/*add Stats component */}
           <div>
               <p>Searching for</p>
                <SearchBox searchAsYouType={false} />
            </div>
            <Hits hitComponent={Hit} /> 
      </div>
      <Pagination /> 
    </InstantSearch>
  </div>
);

export default SearchTemplate;

If you want to change the default statistics, you can also override what’s displayed by creating your own Stats component. Algolia’s usePagination hook provides multiple statistics such as the number of pages, number of hits, etc. You can find a full list of provided variables here. This example will show you how to show the current number of displayed results on a page (i.e. Showing 1 to 7 of 25 results). 

...
import { PaginationConnectorParams } from 'instantsearch.js/es/connectors/pagination/connectPagination';  // import Pagination Params 
import {
  InstantSearch,
  SearchBox,
  Hits,
  usePagination, // import usePagination hook
  Pagination,
  Configure,
} from 'react-instantsearch';
...
function Stats(props: PaginationConnectorParams | undefined) {
  const { currentRefinement, nbHits } = usePagination(props); // read in what page the user is currently on and the total number of hits
  const itemsPerPage = {number of items you set per page};
  const start = currentRefinement * itemsPerPage + 1; // the index of the first displayed result 
  const end = Math.min(start + itemsPerPage - 1, nbHits); // the index of the last displayed result
  if (nbHits === 0) {
    return <div>No results found <div/>;
  }
  return (
    <div>{`Showing ${start} to ${end} of ${nbHits} results`}</div>
  );
}
...

Wrapping Up 

This guide went over some examples of using and customizing Algolia InstantSearch components. You may want to add more components or refactor some logic into their own files. Additional features can be found in the Algolia InstantSearch API.  

Found this article interesting? Chat with our account specialists to get started on your next digital journey.