Conditional display in React InstantSearch Hooks
This guide describes what to do when there are no results, when there’s no query, or when there are errors.
If you want to feature content in your search results based on a set of conditions, you can use Rules to:
- Feature specific data from within your records to, for example, show promotional prices during a sales period
- Display advertisements or promotional banners.
Handling no results
Since not all queries lead to results, it’s essential to let users know when this happens by providing hints on how to adjust the query.
Display a message
The easiest way to display a fallback message when a query doesn’t return results is to use the useInstantSearch()
Hook to create a wrapper component:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function App(props) {
return (
<InstantSearch {...props}>
<SearchBox />
<NoResultsBoundary fallback={<NoResults />}>
<Hits />
</NoResultsBoundary>
</InstantSearch>
);
}
function NoResultsBoundary({ children, fallback }) {
const { results } = useInstantSearch();
// The `__isArtificial` flag makes sure not to display the No Results message
// when no hits have been returned yet.
if (!results.__isArtificial && results.nbHits === 0) {
return (
<>
{fallback}
<div hidden>{children}</div>
</>
);
}
return children;
}
function NoResults() {
const { indexUiState } = useInstantSearch();
return (
<div>
<p>
No results for <q>{indexUiState.query}</q>.
</p>
</div>
);
}
The preceding example lets you pass anything to display results, including <InfiniteHits>
or a custom component that uses the useHits()
Hook.
Let the user clear all filters
If a user makes a mistake, they may 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.
You can achieve this with the <ClearRefinements>
widget.
1
2
3
4
5
6
7
8
9
10
11
12
function NoResults() {
const { indexUiState } = useInstantSearch();
return (
<div>
<p>
No results for <q>{indexUiState.query}</q>.
</p>
<ClearRefinements excludedAttributes={[]} />
</div>
);
}
Handling empty queries
By default, React InstantSearch Hooks always shows you results, even when the query is empty. Depending on your use case and how you build your UI, you may only want to show results when there’s a query.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function App(props) {
return (
<InstantSearch {...props}>
<SearchBox />
<EmptyQueryBoundary fallback={null}>
<Hits />
</EmptyQueryBoundary>
</InstantSearch>
);
}
function EmptyQueryBoundary({ children, fallback }) {
const { indexUiState } = useInstantSearch();
if (!indexUiState.query) {
return fallback;
}
return children;
}
Handling errors
When an error occurs, you might want to display a specific piece of content to help the user go back to the standard state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import React, { useEffect, useState } from 'react';
import * as Toast from '@radix-ui/react-toast';
import { useInstantSearch } from 'react-instantsearch-hooks-web';
function SearchErrorToast() {
const { use } = useInstantSearch();
const [error, setError] = useState(null);
useEffect(() => {
const middleware = ({ instantSearchInstance }) => {
function handleError(searchError) {
setError(searchError);
}
return {
subscribe() {
instantSearchInstance.addListener('error', handleError);
},
unsubscribe() {
instantSearchInstance.removeListener('error', handleError);
},
};
};
return use(middleware);
}, [use]);
if (!error) {
return null;
}
return (
<Toast.Provider>
<Toast.Root
onOpenChange={(isOpen) => {
if (!isOpen) {
setError(null);
}
}}
>
<Toast.Title>{error.name}</Toast.Title>
<Toast.Description>{error.message}</Toast.Description>
</Toast.Root>
<Toast.Viewport />
</Toast.Provider>
);
}
function App(props) {
return (
<InstantSearch {...props}>
<SearchErrorToast />
<SearchBox />
<Hits />
</InstantSearch>
);
}