Prevent blank and initial search with Algolia

If you use Algolia for search in your React application then you might not want it to search for blank queries and prevent search on init. This is how you do it.


Thu Sep 03 2020 - 2 min read

Algolia recent updated their pricing. You no longer have to pay a hefty monthly fee to get search going. It is now entirely based on your search volume and you get 10000 search requests for free every month. This makes it very attractive for blogs like this one.

I follow the official Gatsby guide to get search going which was easy enough, but I ran into a problem. Algolia will by default make a search request on every single page load and another when you focus the search bar. The reasoning for this is that firing off a blank request make the next request faster. However, for people who are trying to limit the number of requests this is a problem. For a popular blog you'd very easily hit the 10k limit even if no one is using your search.

There is no official way to skip the initial or blank search using the Algolia React client so we have to do it ourselves. You probably have something like this in your code if you use the official client:

  const algoliaClient = algoliasearch(
    "ID",
    "KEY"
  );

  return (
    <div ref={rootRef}>
      <InstantSearch
        searchClient={algoliaClient}
        indexName={indices[0].name}
        onSearchStateChange={({ query }) => setQuery(query)}
      >
        <SearchBox onFocus={() => setFocus(true)} hasFocus={hasFocus} />
        <SearchResult
          show={query && query.length > 0 && hasFocus}
          indices={indices}
        />
      </InstantSearch>
    </div>
  );

To fix the issue all you have to is to create your own search client and hook into the search method like so:

  const algoliaClient = algoliasearch(
    "ID",
    "KEY"
  );

  const searchClient = {
    search(requests) {
      if (requests[0].params.query === "") {
        return [];
      }
      return algoliaClient.search(requests);
    },
  };

  return (
    <div ref={rootRef}>
      <InstantSearch
        searchClient={searchClient}
        indexName={indices[0].name}
        onSearchStateChange={({ query }) => setQuery(query)}
      >
        <SearchBox onFocus={() => setFocus(true)} hasFocus={hasFocus} />
        <SearchResult
          show={query && query.length > 0 && hasFocus}
          indices={indices}
        />
      </InstantSearch>
    </div>
  );

There you go! No more searches being fired on initial page load and no more blank searches.