In < Next 13 (or with appDir disabled), you could do:
const MyComponent = () => {
const router = useRouter();
const toggleStatic = () => {
if (router.query.static) {
router.push(router.pathname, router.pathname, { shallow: true });
} else {
router.push(router.pathname, router.pathname + "?static", { shallow: true });
}
}
return <>
// ...
</>
});
This would perform a shallow router update that would change the location, but not push it to history or trigger a page load.
Now, with appDir enabled, you need to import functions from next/navigation
instead. But the docs don't say anything about shallow router pushing using the new router?
All I can do is this:
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const toggleStatic = () => {
if (searchParams.get("static")) {
router.push(pathname);
} else {
router.push(pathname + "?static");
}
};
But that does a full page reload. Is there a way to replicate the shallow router functionality using Next 13's appDir?
In < Next 13 (or with appDir disabled), you could do:
const MyComponent = () => {
const router = useRouter();
const toggleStatic = () => {
if (router.query.static) {
router.push(router.pathname, router.pathname, { shallow: true });
} else {
router.push(router.pathname, router.pathname + "?static", { shallow: true });
}
}
return <>
// ...
</>
});
This would perform a shallow router update that would change the location, but not push it to history or trigger a page load.
Now, with appDir enabled, you need to import functions from next/navigation
instead. But the docs don't say anything about shallow router pushing using the new router?
All I can do is this:
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const toggleStatic = () => {
if (searchParams.get("static")) {
router.push(pathname);
} else {
router.push(pathname + "?static");
}
};
But that does a full page reload. Is there a way to replicate the shallow router functionality using Next 13's appDir?
Share Improve this question asked Apr 13, 2023 at 15:55 brandonscriptbrandonscript 73.3k35 gold badges175 silver badges237 bronze badges 1- 2 see github./vercel/next.js/discussions/48110 – Shahriar Commented Sep 5, 2023 at 11:45
4 Answers
Reset to default 1Try the replace
method instead of push
:
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const toggleStatic = () => {
if (searchParams.get("static")) {
router.replace(pathname);
} else {
router.replace(pathname + "?static");
}
};
useRouter in nextjs docs.
I wrote a custom hooks that solves it in my case:
export function useShallowNavigation(defaultValues: Record<string, unknown> = {}) {
const pathname = usePathname();
const searchParams = useSearchParams();
const [params, setParams] = useState(
Object.entries(defaultValues).reduce((agg, [key, value]) => {
if (!agg[key]) agg[key] = String(value);
return agg;
}, Object.fromEntries(searchParams.entries()))
);
useEffect(() => {
const newUrl = Object.keys(params).length
? `${pathname}?${new URLSearchParams(params).toString()}`
: pathname;
if (newUrl !== window.location.pathname + window.location.search) {
window.history.pushState(
{ ...window.history.state, as: newUrl, url: newUrl },
'',
newUrl
);
}
}, [pathname, params]);
return [params, setParams] as const;
}
The key is to handle the query parameters in an object state, and then sync the url from that state.
Looks like using the native History
api is the officially remended way for this now.
Try to add scroll option to router.push { scroll: false }.
router.push('/updated-route', { scroll: false });
Documentation: https://nextjs/docs/app/building-your-application/routing/linking-and-navigating#disabling-scroll-restoration
Also you can check this thread: Next.js - router.push without scrolling to the top
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745365376a4624552.html
评论列表(0条)