nextjs-toploader
nextjs-toploader copied to clipboard
Compatibility with useRouter
Great Library. Thanks for your work.
So far it works great for Link
components but for useRouter
, it doesn't seem to work at all. Is there some workaround it?
Edit: After going through multiple comments here, I have settled on this approach https://github.com/CivicDataLab/opub-mono/blob/main/apps/www/lib/navigation.tsx
- I can start and stop the progress bar on demand.
- Also using zustand to keep a meta state globally for when page transitioning is happening
+1, it will be great. But I think it's impossible now, with current app dir api. I'll be glad if I'm wrong.
Here is my workaround:
export const usePRouter = () => {
const router = useRouter();
const { push } = router;
router.push = (href, options) => {
NProgress.start();
push(href, options);
};
return router;
};
// add this to a top level component
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
NProgress.done();
}, [pathname, searchParams]);
Here is my workaround:
export const usePRouter = () => { const router = useRouter(); const { push } = router; router.push = (href, options) => { NProgress.start(); push(href, options); }; return router; }; // add this to a top level component const pathname = usePathname(); const searchParams = useSearchParams(); useEffect(() => { NProgress.done(); }, [pathname, searchParams]);
are you using this library or the nprogress ? where is that NProgress coming from?
@PixeledCode Forgot to mention I've forked that library
@PixeledCode Forgot to mention I've forked that library
is your code open? can you share it?
@PixeledCode Nothing different than this repo. You just need to import NProgress
to start/stop anywhere you want.
import * as NProgress from 'nprogress';
It would be great to have this feature! Thank you for your work! :)
@PixeledCode Nothing different than this repo. You just need to import
NProgress
to start/stop anywhere you want.import * as NProgress from 'nprogress';
Thanks for this, this approach worked.
I am getting this warning, Entire page /[locale]/dashboard/dataset/new deopted into client-side rendering.
and since we are using useSearchParams
on top level, I guess this warning will stay, right?
import * as NProgress from 'nprogress';
Do you have a workaround with router.refresh() support? most mutations are now just calling refresh to refetch data.
@PixeledCode Nothing different than this repo. You just need to import
NProgress
to start/stop anywhere you want.import * as NProgress from 'nprogress';
Thanks for this, this approach worked. I am getting this warning,
Entire page /[locale]/dashboard/dataset/new deopted into client-side rendering.
and since we are usinguseSearchParams
on top level, I guess this warning will stay, right?
This can be fixed by wrapping around the component by react suspense.
<Suspense fallback={null}><NProgressTop /></Suspense>
Just put your useRouter
in a function and include NProgress.start();
as @zbeyens mentioned.
Add:
import * as NProgress from "nprogress";
import { useRouter } from "next/navigation";
Example usage:
const router = useRouter();
const handlePush = () => {
NProgress.start();
router.push("/some-page");
};
nextjs-toploader uses NProgress under the hud.
This progress bar package handles Next 13, both <Link>
and router.push()
👍.
You only have to modify your useRouter
imports to import { useRouter } from 'next-nprogress-bar'
.
Works well!
@dan-pugsley awesome!
https://github.com/TheSGJ/nextjs-toploader/issues/10#issuecomment-1538691096 works like a charm, here's a TypeScript version I'm using:
// useRouter.ts
import { useRouter as useBaseRouter } from "next/navigation";
import NProgress from "nprogress";
export function useRouter() {
const router = useBaseRouter();
const { push } = router;
router.push = async (...args: Parameters<typeof push>) => {
NProgress.start();
return push(...args);
};
return router;
}
If you're using the next/router
pages router, this might be of help:
import { useRouter } from "next/router";
import NProgress from "nprogress";
export function useCustomRouter(): ReturnType<typeof useRouter> {
const router = useRouter();
const originalPush = router.push;
router.push = (...args: Parameters<typeof router.push>): ReturnType<typeof originalPush> => {
NProgress.start();
return originalPush(...args);
};
return router;
}
#10 (comment) works like a charm, here's a TypeScript version I'm using:
// useRouter.ts import { useRouter as useBaseRouter } from "next/navigation"; import NProgress from "nprogress"; export function useRouter() { const router = useBaseRouter(); const { push } = router; router.push = async (...args: Parameters<typeof push>) => { NProgress.start(); return push(...args); }; return router; }
Nice solution, but for me it starts loading and never ends
Nice solution, but for me it starts loading and never ends
@rodrigocipriani You will probably need to add some code to make the toploader stop spinning, see: https://github.com/TheSGJ/nextjs-toploader/issues/10#issuecomment-1538691096
This is not a good solution.
This progress bar package handles Next 13, both
<Link>
androuter.push()
👍.You only have to modify your
useRouter
imports toimport { useRouter } from 'next-nprogress-bar'
.Works well!
to use this library with Next 13+, you must turn your RootLayout into a client component with 'use client'. this turns your entire app into a client-rendered app, see the docs.
if your server component do any db fetching or use .env vars that are meant to be private (i.e. not prefixed with NEXT_PUBLIC_), then they will break. you won't be able to directly run server-side database queries on a client environment, and your .env vars will be undefined.
EDIT: fixed broken link to Next docs
This is not a good solution.
This progress bar package handles Next 13, both
<Link>
androuter.push()
👍. You only have to modify youruseRouter
imports toimport { useRouter } from 'next-nprogress-bar'
. Works well!to use this library with Next 13+, you must turn your RootLayout into a client component with 'use client'. this turns your entire app into a client-rendered app, see the docs.
if your server component do any db fetching or use .env vars that are meant to be private (i.e. not prefixed with NEXT_PUBLIC_), then they will break. you won't be able to directly run server-side database queries on a client environment, and your .env vars will be undefined.
So you have to treat it like any other provider wrapper. Usually you will create a separate Provider component, add all of the components like this and then wrap layout with it. It's a pretty common pattern
This is not a good solution. ... if your server component do any db fetching or use .env vars that are meant to be private (i.e. not prefixed with NEXT_PUBLIC_), then they will break. you won't be able to directly run server-side database queries on a client environment, and your .env vars will be undefined.
So you have to treat it like any other provider wrapper. Usually you will create a separate Provider component, add all of the components like this and then wrap layout with it. It's a pretty common pattern
The Provider pattern is fine too, but you're making a 'use-client' component a parent of all of your app. This turns your entire app into part of the client bundle, and none of it will be server rendered. If you don't care about server rendering it's not an issue. If you do however you can't use next-nprogress-bar.
You can do this in Holy Loader ↗
'use client';
import { startHolyLoader } from 'holy-loader';
startHolyLoader();
router.push('/your-page')