I have a tag input that produces an array of tags. Using NextJs's useRouter, I want to add those tags as query string params as they are added. I also need to preserve the current query string params, since other filters, searches, and pagination need to remain.
Here is how I'm currently doing it.
const router = useRouter();
const { query } = router;
const [tags, setTags] = useState([]);
useEffect(() => {
router.push({
query: {
...query,
tags,
},
});
}, [tags, router, query]);
return (
<>
<TagInput tags={tags} setTags={setTags} placeholder="Search by tags" />
</>
);
However, this causes an infinite render since the useEffect updates the query
but also has query
as a dependency. If I remove query
as a dependency, it works fine, but I get the missing dependency linting error.
Edit: Here is a codesandbox with a minimal example that reproduces the issue. It works as is, but if you uncomment the query
dependency, infinite loop.
https://codesandbox.io/s/next-js-dynamic-routing-forked-rlxuqh?file=/pages/index.js
One way this can be done is to directly update the query object and read the tags from the url, rather than storing the tags in state.
const router = useRouter();
const { query } = router;
const setTags = useCallback((tags) => {
router.push({
query: {
...query,
tags
}
});
}, [router, query]);
return (
<>
<TagInput tags={query.tags || []} setTags={setTags} placeholder="Search by tags" />
</>
);