admin管理员组文章数量:1134570
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
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
Share Improve this question edited Apr 27, 2020 at 23:52 Jean-Francois Gagnon asked Apr 27, 2020 at 19:29 Jean-Francois GagnonJean-Francois Gagnon 3,2804 gold badges21 silver badges27 bronze badges 6 | Show 1 more comment13 Answers
Reset to default 72Just add more param to current router then push itself
const router = useRouter();
router.query.NEWPARAMS = "VALUE"
router.push(router)
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 },
});
If we want to have this as a link - use it like so:
const router = useRouter();
<Link
href={{
pathname: router.pathname,
query: { ...router.query, lang },
}}
passHref
shallow
replace
></Link>
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.
An alternative approach when you have dynamic routing in Next.js, and want to do a shallow adjustment of the route to reflect updated query params, is to try:
const router = useRouter()
const url = {
pathname: router.pathname,
query: { ...router.query, page: 2 }
}
router.push(url, undefined, { shallow: true })
This will retreive the current path (router.pathname
) and query (router.query
) details, and merge them in along with your new page
query param. If your forget to merge in the existing query params you might see an error like:
The provided href value is missing query values to be interpolated properly
for nextjs 13 I just found this,
import { useRouter } from 'next/navigation';
router.push(`?page=${page}`)
you just need to handle every query you want
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);
};
If anyone is still looking the answer ,for Next,js ^11.1.2.I hope this helps you out.Use
const router = useRouter();
router.push({ pathname: "/search", query: { key: key } });
In latest version, Next 13, some of the functionality moved to other hooks, which query and path are some of them. You can use useSearchParams
to get query and usePathname
instead of pathname. By the time I am writing this answer, it does not have a stable version and you can find the beta documents here:
https://beta.nextjs.org/docs/api-reference/use-router
If you are using App Router, The query
object has been removed and is replaced by useSearchParams()
, you need to update searchParams
:
export default function ExampleClientComponent() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
// Get a new searchParams string by merging the current
// searchParams with a provided key/value pair
const createQueryString = useCallback(
(name: string, value: string) => {
const params = new URLSearchParams(searchParams.toString())
params.set(name, value)
return params.toString()
},
[searchParams]
)
return (
<>
{/* using useRouter */}
<button
onClick={() => {
// <pathname>?sort=asc
router.push(pathname + '?' + createQueryString('sort', 'asc'))
}}
>
ASC
</button>
{/* using <Link> */}
<Link
href={
// <pathname>?sort=desc
pathname + '?' + createQueryString('sort', 'desc')
}
>
DESC
</Link>
</>
)
}
The best solution I could come up with is that doesn't cause the Unknown key passed via urlObject into url.format
is to do this pattern router.query.plan = plan.title; router.push({ query: router.query });
I see the top answer already resolved this, just wanted to add, if you have for example table filters or page result filters, do not do ‘router.replace()’. Always push to preserve the browser history. This way the user can go back with browser arrows and query params will still work.
let queryParams;
if (typeof window !== "undefined") {
// The search property returns the querystring part of a URL, including the question mark (?).
queryParams = new URLSearchParams(window.location.search);
// quaeryParams object has nice methods
// console.log("window.location.search", queryParams);
// console.log("query get", queryParams.get("location"));
}
inside changeLanguage
,
const changeLanguage = (lang: LanguageID) => {
if (queryParams.has("lang")) {
queryParams.set("lang", lang);
} else {
// otherwise append
queryParams.append("lang", lang);
}
router.replace({
search: queryParams.toString(),
});
};
本文标签: javascriptNextJSAppending a query param to a dynamic routeStack Overflow
版权声明:本文标题:javascript - NextJS - Appending a query param to a dynamic route - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736861294a1955925.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
changeLanguage = (lang: LanguageID)
are you trying to set a default value? Or is this TypeScript syntax? – Antonio Pavicevac-Ortiz Commented Apr 27, 2020 at 21:52pathname
property theasPath
value from the router. – Jose Felix Commented Apr 27, 2020 at 22:18