Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NavigationProgress setup for NextJS13 App Directory #4927

Open
dinogomez opened this issue Sep 29, 2023 · 6 comments
Open

NavigationProgress setup for NextJS13 App Directory #4927

dinogomez opened this issue Sep 29, 2023 · 6 comments
Labels
help wanted Contributions from community are welcome

Comments

@dinogomez
Copy link

dinogomez commented Sep 29, 2023

Link to the page where something nasty is located

https://mantine.dev/others/nprogress/#setup-navigationprogress

Exact quote of what is wrong

Hi, I tried setting up NavigationProgress for NextJS13 App Dir but the guide was not available on v7.1.0 docs. and the older v6.0.21 docs still uses the Pages directory setup show here.

// _pages directory_
// components/RouterTransition.tsx
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { NavigationProgress, nprogress } from '@mantine/nprogress';

export function RouterTransition() {
  const router = useRouter();

  useEffect(() => {
    const handleStart = (url: string) => url !== router.asPath && nprogress.start();
    const handleComplete = () => nprogress.complete();

    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleComplete);
    router.events.on('routeChangeError', handleComplete);

    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleComplete);
      router.events.off('routeChangeError', handleComplete);
    };
  }, [router.asPath]);

  return <NavigationProgress autoReset={true} />;
}

I had a little trouble adapting this to the app directory since next13 app dir uses next/navigation now instead of next/router. I've come up with a way to make this work on the app directory.

It uses usePathname to check the current url and useSearchParams to let you read the URL's query string. This provides a actual start to finish for request.

"use client";
import { useEffect } from "react";
import { usePathname, useSearchParams } from "next/navigation";
import { NavigationProgress, nprogress } from "@mantine/nprogress";

export function RouterTransition() {
  const pathname = usePathname();
  const searchParams = useSearchParams();

  useEffect(() => {
    nprogress.complete();
    return () => {
      nprogress.start();
    };
  }, [pathname, searchParams]);

  return <NavigationProgress size={5} />;
}

Example of it being used on a handleSubmit function from a form's onSubmit

 const handleSubmit = async (values: (typeof form)["values"]) => {
    setLoading(true);
    nprogress.start();
    //DO STUFF HERE 
    //{

    //}
    setLoading(false);
    nprogress.complete();
  };

And being used in the body just like in the old docs.

<body>
      <MantineProvider
        theme={{
          primaryColor: "bright-pink",
          colors: {
            "bright-pink": [
              "#fff4e2",
              "#ffe9cc",
              "#ffd09c",
              "#fdb766",
              "#fca13a",
              "#fb931d",
              "#fc8c0c",
              "#e17900",
              "#c86a00",
              "#ae5a00",
            ],
          },
        }}
      >
        <RouterTransition />
        {children}
      </MantineProvider>
    </body>

I'm kinda new to open source contributing, so I am not particular sure if this serves as a proper Issue.

Thanks,

@mateuscqueiros
Copy link
Contributor

Hello! I too am interested in this. It looks like this is a problem with Next 13, currently it doesn't supports router events as you pointed. If you are not using Next then it isn't a problem since the component works well with the pure React Router. But for us Next users I think the only solution is to wait for a proper Router in Next.

@rtivital rtivital added the help wanted Contributions from community are welcome label Oct 1, 2023
@rtivital
Copy link
Member

rtivital commented Oct 1, 2023

Help wanted with documentation update

@smyja
Copy link

smyja commented Oct 13, 2023

Here's what i am using.

// components/RouterTransition.tsx
import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'
import { nprogress, NavigationProgress } from '@mantine/nprogress';

export function RouterTransition() {

  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    nprogress.complete();
    return () => {
   
    };
  }, [pathname, searchParams]);
  return <NavigationProgress autoReset={true} />;
}

@pshivvy
Copy link

pshivvy commented Nov 3, 2023

Here's what i am using.

// components/RouterTransition.tsx
import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'
import { nprogress, NavigationProgress } from '@mantine/nprogress';

export function RouterTransition() {

  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    nprogress.complete();
    return () => {
   
    };
  }, [pathname, searchParams]);
  return <NavigationProgress autoReset={true} />;
}

How does this work for you without you getting an error for 'use client' since you are using useEffect?

@pzehle
Copy link

pzehle commented Nov 4, 2023

This is my implementation, I just added a delay so it actually shows something and it is not immediately gone:

'use client';

import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';
import { NavigationProgress, nprogress } from '@mantine/nprogress';

export function RouterTransition() {

	// Get path and params
	const pathname = usePathname();
	const searchParams = useSearchParams();

	// Listen to changes
	useEffect(() => {
		
		// Complete after 1s delay
		setTimeout(() => nprogress.complete(), 1000);
		
		return () => {

			// Start bar
			nprogress.start();

		};

	}, [pathname, searchParams]);

	return <NavigationProgress size={5} />;
	
}

However, I wonder how to implement this before the route changes, so when NextJS is pre-fetching the page, something like YouTube does for example. But this is a start anyway.

EDIT:
Well I found some example and I was able to do what I wanted. Here the repo: https://github.com/joulev/nextjs13-appdir-router-events/tree/main

@JulianDM1995
Copy link

JulianDM1995 commented Jan 29, 2024

The given solution works fine in dev, but fails during build, due to a Suspense Boundary issue using Next.js V14.1.
If anyone is facing that problem, this will do the trick:

'use client'
import { NavigationProgress, nprogress } from '@mantine/nprogress'
import { usePathname } from 'next/navigation'
import { useEffect } from 'react'

export const RouterTransition = () => {
  const pathname = usePathname()

  useEffect(() => {
    nprogress.complete()
    return () => {
      nprogress.start()
    }
  }, [pathname])

  return <NavigationProgress size={5} />
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Contributions from community are welcome
Projects
None yet
Development

No branches or pull requests

7 participants