Reputation: 7743
I am writing a search component which uses react query to fetch the data.
export default function useSearchResults({
query,
}: IUseGetSearchResultsProps): QueryObserverResult<IResponse<ISearchResult>> {
return useQuery(
[SEARCH_RESULT_QUERY_KEY, { query }],
(): Promise<IResponse<ISearchResult>> => getSearchResults({ query }),
{
enabled: false,
keepPreviousData: true,
}
);
}
Which I then import in my component, and refetch the data when the user enters a search term:
const [searchTerm, setSearchTerm] = React.useState<string>("");
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
e.preventDefault();
setSearchTerm(e.target.value);
};
const { data, refetch } = useSearchResults({ query: searchTerm });
React.useEffect(() => {
if (searchTerm.length > 0) {
refetch();
}
}, [searchTerm]);
There is a requirement to not show any data when there is nothing in the searchTerm
i.e. searchTerm
is an empty string.
However, the API returns all results when a search term is not passed to it and I cannot alter that behaviour.
Is there a way to reset useQuery
hook to return data
as an empty array?
Upvotes: 7
Views: 35295
Reputation: 28833
Let me please point out that disabling a query and using refetch
in an effect is not per-se idiomatic react-query.
Since react-query will automatically refetch whenever the query key changes, and you also already have local state that you put into the query key, you can drive the enabled
flag with that information and get rid of the effect:
export default function useSearchResults({
query,
}: IUseGetSearchResultsProps): QueryObserverResult<IResponse<ISearchResult>> {
return useQuery(
[SEARCH_RESULT_QUERY_KEY, { query }],
(): Promise<IResponse<ISearchResult>> => getSearchResults({ query }),
{
enabled: Boolean(query),
keepPreviousData: true,
}
);
}
const [searchTerm, setSearchTerm] = React.useState("");
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
e.preventDefault();
setSearchTerm(e.target.value);
};
const { data, refetch } = useSearchResults({ query: searchTerm });
The query will start disabled
and will enable
itself, with all the react-query advantages like background updates as soon as the user has typed in a query, and it will also refetch when the input changes.
Since the query will be disabled for an empty string, the backend api should never be hit with that, so your data will stay undefined
, which you can then coerce to empty array.
Upvotes: 7
Reputation: 6512
What I would do is modify the response in the useQuery hook before returning it from useSearchResults
.
function useSearchResults({ query }) {
return useQuery(["search", { query }], () => {
if (!query) return [];
return getSearchResults({ query });
});
}
Notice how it doesn't immediately return getSearchResults
? The query function is a good place to perform transforms and such as they're needed.
I'm not completely sure of the UX but it sounds like you want to show results, then filter results based on a search term, and then if the search box has an empty string, display no results? If you can clear this up I can modify the example below.
Here's a sandbox to demonstrate this: https://codesandbox.io/s/nifty-wilbur-xbcfy
Upvotes: 1