I looked at this example of how to write a search field that only searches when the user stops typing. I made my own implementation with apollo client here:
const SEARCH_QUERY = gql`
query Search($terms: [String]!) {
search(terms: $terms) {
id
title
desc
imagePreview
}
}
`;
const Browse = () => {
const [searchKeyword, setSearchKeyword] = useState("");
const [searchQuery, { loading: searchLoading, error: searchError, data: searchData },] = useLazyQuery(SEARCH_QUERY, {
variables: { terms: searchKeyword.split(" ") },
fetchPolicy: "network-only",
}); // get new courses by searched terms
useEffect(
() => {
const delayDebounceFn = setTimeout(() => {
console.log(searchKeyword);
// Debounce only works first time. The function below gets called even when the above console.log isn't shown in the console.
searchQuery();
}, 3000);
return () => clearTimeout(delayDebounceFn);
},
[searchKeyword]
);
return (
<div>
<input
autoFocus
type="text"
autoComplete="off"
placeholder="Search here..."
onChange={(e) => setSearchKeyword(e.target.value)}
/>
{searchLoading ? <p>Loading...</p> : searchData ? <Row items={searchData.search}/>}
</div>
);
};
It works fine, but only the first time. As soon as the first request has been sent the search keyword just gets updated immediately and sends a new request on every type. The most bizarre thing is that the console.log(searchKeyword) doesn't show up, but the searchQuery function is still getting called.
EDIT: I figured it out. The problem was that i was using a different variable every time in my UseLazyQuery (also described here on a github issue). All i had to do was change my query variables from this:
const [searchQuery, { loading, error, data}] = useLazyQuery(SEARCH_QUERY, {
variables: { terms: searchKeyword.split(" ") },
fetchPolicy: "network-only",
}); // get new courses by searched terms
...to this:
const [searchQuery, { loading, error, data}] = useLazyQuery(SEARCH_QUERY, {
variables: { terms: searchKeyword },
fetchPolicy: "network-only",
}); // get new courses by searched terms
I just ended up splitting the terms on the server instead of the client. Thanks for the help guys :).