'NextJS - Appending a query param to a dynamic route
In my NextJS app, I have a language selector that's visible on every page. When I select a new language, I just want to replace the current URL by appending a query param lang=en
to it.
Here's the function that replaces the URL:
const changeLanguage = (lang: LanguageID) => {
replace({
pathname,
query: { ...query, lang },
});
};
In this example, replace
, query
and pathname
are coming from the next router.
Now, everything works for static routes, but I'm unable to make it work for dynamic routes. For example, I have the following folder structure:
pages
|_customers
|__index.tsx
|__[customerId].tsx
If I'm on http://localhost/customers
and I change my language to English, the URL changes to http://localhost/customers?lang=en
which is what I want. However, if I'm on http://localhost/customer/1
and I change my language to English, the URL changes to http://localhost/customers/[customerId]?customerId=1&lang=en
, instead of the URL I'm expecting http://localhost/customers/1?lang=en
.
Now, I know that I could use asPath
on the router, and reconstruct the query string object by appending lang
to it, but I feel that it's something that should be build into Next. Also, I know it could be easily done with vanilla JS, but it's not the point here.
Am I missing something? Is there an easier way to append query params to a dynamic route without doing a server-side re-rendering?
Thanks
Solution 1:[1]
Just add more param to current router then push itself
const router = useRouter();
router.query.NEWPARAMS = "VALUE"
router.push(router)
Solution 2:[2]
If we want to have this as a link - use it like so:
// ...
const { query } = useRouter();
// ...
<Link
href={{
pathname: router.pathname,
query: { ...query, lang },
}}
passHref
shallow
replace
></Link>
Solution 3:[3]
I ended up using the solution that I wanted to avoid in the first place, which was to play with the asPath
value. Atleast, there's no server-side re-rendering being done since the path is the same.
Here's my updated changeLanguage
function (stringifyUrl
is coming from the query-string
package)
const changeLanguage = (lang: LanguageID) => {
const newPathname = stringifyUrl({ url: pathname, query: { ...query, lang } });
const newAsPath = stringifyUrl({ url: asPath, query: { lang } });
replace(newPathname, newAsPath);
};
Solution 4:[4]
The solution which doesn't need to send the whole previous route, as replace
just replaces what we need to replace, so query params:
const router = useRouter();
router.replace({
query: { ...router.query, key: value },
});
Solution 5:[5]
I tried adding my param to the route query and pushing the router itself, as mentioned here, it works, but I got a lot of warnings:
So, I then pushed to /
and passed my query params as following:
const router = useRouter();
router.push({ href: '/', query: { myQueryParam: value } });
I hope that works for you too.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Cong Nguyen |
Solution 2 | |
Solution 3 | Jean-Francois Gagnon |
Solution 4 | Maciej Sikora |
Solution 5 | albert |