Reputation: 5358
I am using NextJs, and I have a component that uses useDebounceHook. The component looks like this.
import { useRouter } from 'next/router';
function SearchComponent() {
const router = useRouter();
const [searchResults, setSearchResults] = useState([]);
const [searchTerm, setSearchTerm] = useState<string>('');
const debouncedSearchTerm: string = useDebounce<string>(searchTerm, 250);
const handleSearchChange = (event) => {
setSearchTerm(event.target.value);
};
useEffect(() => {
const newPath = `/search?q=${debouncedSearchTerm}`;
router.push(newPath, undefined, { shallow: true });
}, [debouncedSearchTerm]);
// eslint complains above that router is missing and if we add, the function runs infintely.
useEffect(() => {
fetchQueryResults()
.then((data) => {
setSearchResults(data)l
})
}, [router.query.q]);
return (
<InputField
placeholder="Search"
value={searchTerm}
onChange={handleSearchChange}
/>
{renderSearchResults()}
)
}
// useDebounceHook reference: https://usehooks.com/useDebounce/
The component listens to the search change event and immediately updates the value as it needs to be visible on the screen textbox. However, it debounces the value for fetching search results.
And we want to do the fetch from the URL route as we want it to be bookmarkable. Hence we push the query param to the URL once the debounce value changes rather than directly fetching.
Here the problem is Eslint complains that we are missing router from the dependency array. If we add it, it goes into an infinite loop.
How to solve this issue? Is it ok if we skip adding the router to the dependency array?
Upvotes: 0
Views: 3652
Reputation: 184
I did this temporary fix until the larger issue is resolved from nextjs:
useEffect(() => {
const newPath = `/search?q=${debouncedSearchTerm}`;
router.push(newPath, undefined, { shallow: true });
// This is a hack to prevent the redirect infinite loop problem
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [undefined]);
Upvotes: 0
Reputation: 7326
One option is to only do the router push if it changes q
, i.e.
useEffect(() => {
const newPath = `/search?q=${debouncedSearchTerm}`;
if (debouncedSearchTerm !== router.query.q) {
router.push(newPath, undefined, { shallow: true });
}
}, [router, debouncedSearchTerm]);
However I think it's also fine to omit router as a dependency here (and suppress the lint), since you don't need to re-navigate if the router changes (generally when dependencies change you want to rerun the effect, but here router doesn't seem necessary).
One thing to consider is if the page changes from some other reason (ex. they click a link on the page which takes them to "search?q=blah"), what should happen? Should the effect run taking them back to search?q=searchTerm
? This is essentially the case being handled here.
Upvotes: 1