Guides / Building Search UI / Going further

Handling no results

Not all queries lead to results, and it’s important to let users know when this happens. This gives you an opportunity to provide hints on how to adjust the query. This way, you can ensure users don’t leave your website or search using an external search engine.

Display a message

The easiest way to display a fallback message when a query doesn’t return results is to use the templates.empty option.

1
2
3
4
5
6
7
8
search.addWidgets([
  instantsearch.widgets.hits({
    container: 'hits',
    templates: {
      empty: '<div>No results have been found for {{ query }}</div>.'
    }
  })
]);

Note that the above example also works with infiniteHits.

Let the user clear all filters

Users make mistakes, which can cause them to not find any results. You can account for this by providing a way to clear filters right from the “no results” state, so they can start over.

For this purpose, we provide a specific widget called clearRefinements. However, you can’t use it inside the empty template, so in this case you need to leverage the routing instead.

First, you need to activate the URL sync mechanism, so that you can easily clear the filters using the URL.

1
2
3
const search = instantsearch({
  routing: true
});

Check out the complete routing guide if you want to learn more.

The routing makes your InstantSearch.js app aware of changes in the URL. This lets you influence the parameters of the search, and therefore clear filters by removing URL parameters.

1
2
3
4
5
6
7
8
9
10
11
search.addWidgets([
  instantsearch.widgets.hits({
    container: 'hits',
    templates: {
      empty: `<div>
                <p>No results have been found for {{ query }}</p>
                <a role="button" href=".">Clear all filters</a>
              </div>`
    }
  })
]);

Handling empty queries

By default, InstantSearch.js always shows you results, even when the query is empty. Depending on your use case and the way you want to build your UI, you may want to only show results when there’s a query.

Using the helper state

This hides the results container when the query is empty.

1
2
3
4
5
6
7
8
const search = instantsearch({
  searchFunction(helper) {
    const container = document.querySelector('#results');
    container.style.display = helper.state.query === '' ? 'none' : '';

    helper.search();
  }
});

Using a connector

This uses the connectHits connector.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const customHits = instantsearch.connectors.connectHits(
  (renderOptions, isFirstRender) => {
    const { results, widgetParams } = renderOptions;
    const { container } = widgetParams;

    container.innerHTML =
      results && results.query
        ? `<div>Searching for query "${results.query}".</div>`
        : `<div>No query</div>`;
  }
);

search.addWidgets([
  customHits({
    container: document.querySelector('#hits')
  })
]);

Handling errors

When an error occurs, you might want to display a specific piece of content to help the user go back to a normal state.

Making an error-handling widget

You can build a custom widget to handle errors when they occur. If you want to learn more about custom widgets, check out the guide.

1
2
3
4
5
6
7
8
9
search.addWidgets([
  {
    init({ helper }) {
      helper.on('error', error => {
        console.error('Error', error);
      });
    }
  }
]);

You can improve this custom widget by writing a more meaningful error message, adapting it to your UI, figuring out whether the user is online or not, and log the error in your monitoring system.

Did you find this page helpful?