DasBeasto
DasBeasto

Reputation: 2282

Prevent useEffect infinite loop when updating NextJs query string

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

Upvotes: 0

Views: 1520

Answers (1)

Stafford Rose
Stafford Rose

Reputation: 807

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" />
  </>
);

Upvotes: 2

Related Questions