apal21 / nextjs-progressbar

A simple Next.js progressbar component using NProgress.
https://www.npmjs.com/package/nextjs-progressbar
MIT License
776 stars 61 forks source link

router.events.emit('routeChangeError'); is not working #70

Closed nino-cast closed 2 years ago

nino-cast commented 2 years ago
image
"next": "12.0.10",
"nextjs-progressbar": "^0.0.13",
// app.tsx

...
<NextNProgress stopDelayMs={0} options={{ showSpinner: false }} />
// form guard

import { useRouter } from 'next/router';
import { useEffect } from 'react';

export const useFormGuard = (isDirty: boolean) => {
  const router = useRouter();
  const message = 'ok?';

  const pageChangeHandler = () => {
    const answer = window.confirm(message);
    if (!answer) {
      // crash here
      router.events.emit('routeChangeError');
      // throw 'routeChange aborted.';
    }
  };

  const beforeUnloadhandler = (event: BeforeUnloadEvent) => {
    event.preventDefault();
    event.returnValue = message;
  };

  useEffect(() => {
    if (isDirty) {
      router.events.on('routeChangeStart', pageChangeHandler);
      window.addEventListener('beforeunload', beforeUnloadhandler);
      return () => {
        router.events.off('routeChangeStart', pageChangeHandler);
        window.removeEventListener('beforeunload', beforeUnloadhandler);
      };
    }
  }, [isDirty, router]);
};
apal21 commented 2 years ago

Is this related to this package? If so could you please share codesandbox something similar?

imranbarbhuiya commented 2 years ago

This isn't related to this package but ik the solution. You are emitting routeChangeError without any arguments. If you check https://nextjs.org/docs/api-reference/next/router

you'll find routeChangeError emits with 3 args.

routeChangeError(err, url, { shallow }) - Fires when there's an error when changing routes, or a route load is cancelled.

So you need to provide error, url and an object with shallow property.

btw I'm saying to @apal21 that our routeChangeError's handler is set to routeChangeEnd which accepts only url and {shallow} and routeChangeError emits with 3 args and 1st one is error. How it's working? I'll test it later

nino-cast commented 2 years ago

@apal21 @imranbarbhuiya Thank you for your reply. This is demo.

As @imranbarbhuiya points out, I think the cause of the error is the lack of arguments in the handler for routerChangeError. https://github.com/apal21/nextjs-progressbar/blob/master/src/index.tsx#L87-L92

The documentation has a shallow as the third error event, but the library handler is trying to get the shallow from the second argument.

imranbarbhuiya commented 2 years ago

Using {shallow} in url is incorrect. But this wont throw any error bc url.shallow is undefined so it'll assume it as false which will work fine but it needs a fix though. But in your case this isn't the issue. You aren't passing any parameters when using emit which is causing the error.

You should do like this

router.events.emit('routeChangeError',err, yoururl, {shallow})
nino-cast commented 2 years ago

@imranbarbhuiya thank you for your reply.

I understand that the argument is for listen, not emit. When passing the argument with emit, what kind of content should be specifically passed?

Upon investigation, I could not find an example of passing an argument with emit.

I fork and fix the event handler and try.

@apal21 If you know of Sandox where router.events.emit ('routeChangeError'); works for this library, please let me know.

imranbarbhuiya commented 2 years ago

this can help maybe

const pageChangeHandler = (
    url: string,
    { shallow }: { shallow: boolean }
  ) => {
    if (!shallow) {
      const answer = window.confirm(message);
      if (!answer) {
        router.events.emit('routeChangeError','routeChange aborted.', url, {shallow});
        throw 'routeChange aborted.';
      }
    }
  };
nino-cast commented 2 years ago

@imranbarbhuiya solved. Thank you for your kind answer!