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

Feature request: delay option #169

Open
fridays opened this issue Feb 20, 2017 · 9 comments · May be fixed by #207
Open

Feature request: delay option #169

fridays opened this issue Feb 20, 2017 · 9 comments · May be fixed by #207

Comments

@fridays
Copy link

fridays commented Feb 20, 2017

It would be nice to have a delay option, which will only show the progress bar if .done was not already called within the delay time:

NProgress.configure({delay: 80}) // Only show if not done within 80ms
@steida
Copy link

steida commented Mar 30, 2017

https://github.com/este/next/blob/aa41364278e7d01a4a77319111b6fdf78935ecc3/components/loading-bar.js

@rstacruz
Copy link
Owner

you can implement this with something like lodash.debounce:

const debounce = require('lodash.debounce')

const start = debounce(NProgress.start, 80)

@rstacruz rstacruz reopened this Mar 31, 2017
@rstacruz
Copy link
Owner

On second thought, that doesn't really cover it!

@MickL
Copy link

MickL commented Dec 23, 2017

Looking forward for this great new feature! Use case:

A singlepage-app may have pages with zero loading time but the progress bar is shown anyway which is kind of confusing to the user. Would be nice to have a delay exactly as @fridays described: Only show the progress bar if NProgress.done() has not been called within this time.

I would recommend to set the delay on NProgress default to 50-250ms.

Currently i have to do it manually which is not a big deal but integrated within NProgress would be much cleaner:

progressTimeout;

// [...]

switch (routeEvent) {
     case NavigationStart:
          this.progressTimeout = setTimeout(() => {
               NProgress.start();
          }, 250);
          break;
     case NavigationEnd:
     case NavigationCancel:
     case NavigationError:
          clearTimeout(this.progressTimeout);
          NProgress.done();
          break;
}

@fracz
Copy link

fracz commented Jan 22, 2019

Extend the lib before you use it:

NProgress.doStart = NProgress.start;
NProgress.doDone = NProgress.done;
NProgress.clearDelay = function () {
  if (this.startDelay) {
    clearTimeout(this.startDelay);
    this.startDelay = undefined;
  }
}
NProgress.start = function () {
  this.clearDelay();
  this.startDelay = setTimeout(function () {
    NProgress.doStart();
  }, this.settings.delay || 0);
};
NProgress.done = function () {
  this.clearDelay();
  this.doDone();
};

and then:

NProgress.configure({showSpinner: false, delay: 250}).start();

fracz added a commit to iisg/nprogress that referenced this issue Jan 22, 2019
@fracz fracz linked a pull request Jan 22, 2019 that will close this issue
@msurdi
Copy link

msurdi commented Feb 8, 2019

I've extended @fracz idea to avoid patching the library, in case anyone else finds it useful:

let progressBarTimeout = null;

const clearProgressBarTimeout = () => {
  if (progressBarTimeout) {
    clearTimeout(progressBarTimeout);
    progressBarTimeout = null;
  }
};

const startProgressBar = () => {
  clearProgressBarTimeout();
  progressBarTimeout = setTimeout(() => {
    nprogress.start();
  }, 200);
};

const stopProgressBar = () => {
  clearProgressBarTimeout();
  nprogress.done();
};

just use startProgressBar and stopProgressBar instead of nprogress.start/done

@henrik
Copy link

henrik commented May 23, 2020

@msurdi I believe you could simplify that to:

let progressBarTimeout = null;

const startProgressBar = () => {
  clearTimeout(progressBarTimeout);
  progressBarTimeout = setTimeout(nprogress.start, 200);
};

const stopProgressBar = () => {
  clearTimeout(progressBarTimeout);
  nprogress.done();
};

To quote https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout:

Passing an invalid ID to clearTimeout() silently does nothing; no exception is thrown.

And https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout says:

It is guaranteed that a timeout ID will never be reused by a subsequent call to setTimeout() or setInterval() on the same object (a window or a worker). However, different objects use separate pools of IDs.

So it's fine to run clearTimeout without checking first – it won't explode on null or old values, and values won't be reused.

@erwinstone
Copy link

For typescript users:

let progressBarTimeout: number | undefined = undefined

const startProgressBar = () => {
  clearTimeout(progressBarTimeout)
  progressBarTimeout = setTimeout(nProgress.start, 200)
}

const stopProgressBar = () => {
  clearTimeout(progressBarTimeout)
  nProgress.done()
}

@tvanbeek
Copy link

tvanbeek commented Jan 10, 2024

For React you can use this component:

// /src/components/Progress.tsx

import NProgress from "nprogress";
import { useEffect } from "react";

export const Progress = () => {
  // config
  NProgress.configure({
    showSpinner: false,
  });

  useEffect(() => {
    const timeout = setTimeout(NProgress.start, 250); // 250ms

    return () => {
      clearTimeout(timeout);
      NProgress.done();
    };
  });

  return;
}

And then show it when something is loading:

// /src/somePageOrComponent.tsx
import { Progress } from "@/components/Progress";

...
return (
  <>
    {
      somethingIsLoading ? <Progress /> : null;
    }
    <h1>Hello World</h1>
  </>
)
...

Or with Suspense

import { Progress } from "@/components/Progress";

...
<Suspense fallback={<Progress />}>
  <MyAsyncComponent />
</Suspense>
...

In Next.js you can use the same component to show nprogress on route changes. Just create a loading.ts file and export the component (For more information see loading.js file convention for Next.js App Router):

// /src/app/my/route/loading.ts

import { Progress } from "@/components/Progress";
export default Progress;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants