nprogress vs react-top-loading-bar
Implementing Top Loading Indicators in React Applications
nprogressreact-top-loading-barSimilar Packages:

Implementing Top Loading Indicators in React Applications

Both nprogress and react-top-loading-bar are libraries designed to display a slim progress bar at the top of the screen during page loads or asynchronous operations. nprogress is a framework-agnostic vanilla JavaScript library that has been the industry standard for years, offering an imperative API to manually control progress states. react-top-loading-bar is a React-specific implementation that wraps this functionality into a component, aligning better with React's declarative paradigm and lifecycle management.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
nprogress026,414-13511 years agoMIT
react-top-loading-bar075070.3 kB4a year agoMIT

nprogress vs react-top-loading-bar: Architecture and Integration Compared

Both nprogress and react-top-loading-bar solve the same user experience problem: indicating that a background process is running by showing a slim bar at the top of the viewport. However, they approach this from different architectural angles. nprogress is a vanilla JavaScript utility that treats the progress bar as a global singleton, while react-top-loading-bar treats it as a React component. Let's compare how they handle integration, state, and customization.

🧩 Integration Model: Global Singleton vs Component

nprogress operates as a global module.

  • You import the library once and call methods directly.
  • It manipulates the DOM directly, outside of React's render cycle.
  • Requires manual cleanup to prevent conflicts during unmounting.
// nprogress: Imperative global API
import NProgress from 'nprogress';

function startLoading() {
  NProgress.start();
}

function finishLoading() {
  NProgress.done();
}

react-top-loading-bar operates as a component.

  • You place the component once in your root layout.
  • It uses React refs or context to trigger updates.
  • Handles DOM cleanup automatically when the component unmounts.
// react-top-loading-bar: Component-based API
import ReactTopLoadingBar from 'react-top-loading-bar';
import { useRef } from 'react';

function App() {
  const ref = useRef(null);

  const startLoading = () => ref.current?.continuousStart();
  const finishLoading = () => ref.current?.complete();

  return (
    <>
      <ReactTopLoadingBar ref={ref} color="#29d" />
      {/* Other components */}
    </>
  );
}

⚛️ React Lifecycle Management

nprogress requires you to manage side effects manually.

  • You must call NProgress.start() inside useEffect or event handlers.
  • You are responsible for ensuring NProgress.done() is called even if errors occur.
  • Can lead to stale bars if navigation happens before completion.
// nprogress: Manual lifecycle management
useEffect(() => {
  NProgress.start();
  fetchData().then(() => NProgress.done());
  return () => NProgress.remove(); // Cleanup on unmount
}, []);

react-top-loading-bar aligns with React's lifecycle.

  • The component mounts and unmounts with your tree.
  • Ref methods allow imperative control without breaking React rules.
  • Reduces risk of memory leaks or orphaned DOM nodes.
// react-top-loading-bar: Integrated lifecycle
useEffect(() => {
  ref.current?.continuousStart();
  fetchData().then(() => ref.current?.complete());
  // No manual DOM cleanup needed
}, []);

🎨 Customization and Styling

nprogress uses CSS and a configuration object.

  • You import a CSS file or write your own styles targeting #nprogress.
  • Configuration is set via NProgress.configure({}).
  • Global styles can sometimes leak or conflict with CSS modules.
// nprogress: CSS + Config object
import 'nprogress/nprogress.css';
NProgress.configure({ showSpinner: false });

/* CSS */
#nprogress .bar { background: #29d; }

react-top-loading-bar uses props for styling.

  • You pass colors and heights directly as component props.
  • No need to import external CSS files for basic setup.
  • Styles are scoped to the component instance.
// react-top-loading-bar: Props-based styling
<ReactTopLoadingBar 
  color="#29d" 
  height={3} 
  shadow 
  onRef={ref => setRef(ref)} 
/>

🌐 Framework Agnosticism vs React Specificity

nprogress works anywhere JavaScript runs.

  • Use the same code in React, Vue, Svelte, or vanilla sites.
  • Great for micro-frontends where different frameworks coexist.
  • No React dependency, keeping bundle lighter for non-React parts.
// nprogress: Works in any JS context
// Can be used in a Vue mixin or Angular service identically
NProgress.start();

react-top-loading-bar is locked to the React ecosystem.

  • Cannot be used outside of a React component tree.
  • Depends on react and react-dom packages.
  • Better tree-shaking support within React build tools.
// react-top-loading-bar: React only
// Will throw errors if used outside a React component
<ReactTopLoadingBar />

⚠️ Error Handling and Edge Cases

nprogress leaves error handling to the developer.

  • If a promise rejects, the bar stays forever unless you catch it.
  • You must explicitly call NProgress.done() in .finally() blocks.
  • More flexible but requires disciplined coding patterns.
// nprogress: Manual error handling
fetchData()
  .then(() => NProgress.done())
  .catch(() => NProgress.done()); // Must remember this

react-top-loading-bar encourages structured handling.

  • Since it is often tied to component state, errors may reset the UI naturally.
  • Still requires manual completion calls, but ref safety checks help.
  • Optional chaining on refs prevents crashes if component isn't ready.
// react-top-loading-bar: Safer ref calls
fetchData()
  .then(() => ref.current?.complete())
  .catch(() => ref.current?.complete());

🤝 Similarities: Shared Ground Between Both Libraries

Despite the architectural differences, both libraries share core functionality and goals. Here are key overlaps:

1. 📍 Visual Placement

  • Both render a fixed bar at the very top of the viewport.
  • Designed to be unobtrusive and not block user interaction.
// Both achieve this visual result
// nprogress: <div id=

How to Choose: nprogress vs react-top-loading-bar

  • nprogress:

    Choose nprogress if you are working in a vanilla JavaScript environment or need a single solution that works across multiple frameworks like Vue, Angular, and React without changing dependencies. It is ideal for legacy projects or architectures where global imperative control is preferred over component-based state management. However, be prepared to manually manage subscriptions and cleanup within React hooks to avoid memory leaks.

  • react-top-loading-bar:

    Choose react-top-loading-bar if you are building a modern React application and want a solution that integrates naturally with your component tree. It is suitable for projects that prioritize declarative patterns, as it handles mounting and unmounting automatically without requiring manual cleanup in useEffect. This package reduces boilerplate code and aligns with React best practices for UI elements.

README for nprogress

NProgress

Slim progress bars for Ajax'y applications. Inspired by Google, YouTube, and Medium.

Installation

Add nprogress.js and nprogress.css to your project.

<script src='nprogress.js'></script>
<link rel='stylesheet' href='nprogress.css'/>

NProgress is available via bower and npm and spm.

$ bower install --save nprogress
$ npm install --save nprogress

Basic usage

Simply call start() and done() to control the progress bar.

NProgress.start();
NProgress.done();

Using Turbolinks or similar? Ensure you're using Turbolinks 1.3.0+, and use this: (explained here)

$(document).on('page:fetch',   function() { NProgress.start(); });
$(document).on('page:change',  function() { NProgress.done(); });
$(document).on('page:restore', function() { NProgress.remove(); });

Ideas

  • Add progress to your Ajax calls! Bind it to the jQuery ajaxStart and ajaxStop events.

  • Make a fancy loading bar even without Turbolinks/Pjax! Bind it to $(document).ready and $(window).load.

Advanced usage

Percentages: To set a progress percentage, call .set(n), where n is a number between 0..1.

NProgress.set(0.0);     // Sorta same as .start()
NProgress.set(0.4);
NProgress.set(1.0);     // Sorta same as .done()

Incrementing: To increment the progress bar, just use .inc(). This increments it with a random amount. This will never get to 100%: use it for every image load (or similar).

NProgress.inc();

If you want to increment by a specific value, you can pass that as a parameter:

NProgress.inc(0.2);    // This will get the current status value and adds 0.2 until status is 0.994

Force-done: By passing true to done(), it will show the progress bar even if it's not being shown. (The default behavior is that .done() will not do anything if .start() isn't called)

NProgress.done(true);

Get the status value: To get the status value, use .status

Configuration

minimum

Changes the minimum percentage used upon starting. (default: 0.08)

NProgress.configure({ minimum: 0.1 });

template

You can change the markup using template. To keep the progress bar working, keep an element with role='bar' in there. See the default template for reference.

NProgress.configure({
  template: "<div class='....'>...</div>"
});

easing and speed

Adjust animation settings using easing (a CSS easing string) and speed (in ms). (default: ease and 200)

NProgress.configure({ easing: 'ease', speed: 500 });

trickle

Turn off the automatic incrementing behavior by setting this to false. (default: true)

NProgress.configure({ trickle: false });

trickleRate and trickleSpeed

You can adjust the trickleRate (how much to increase per trickle) and trickleSpeed (how often to trickle, in ms).

NProgress.configure({ trickleRate: 0.02, trickleSpeed: 800 });

showSpinner

Turn off loading spinner by setting it to false. (default: true)

NProgress.configure({ showSpinner: false });

parent

specify this to change the parent container. (default: body)

NProgress.configure({ parent: '#container' });

Customization

Just edit nprogress.css to your liking. Tip: you probably only want to find and replace occurrences of #29d.

The included CSS file is pretty minimal... in fact, feel free to scrap it and make your own!

Resources

Support

Bugs and requests: submit them through the project's issues tracker.
Issues

Questions: ask them at StackOverflow with the tag nprogress.
StackOverflow

Chat: join us at gitter.im.
![Chat](http://img.shields.io/badge/gitter-rstacruz / nprogress-brightgreen.svg)

Thanks

NProgress © 2013-2014, Rico Sta. Cruz. Released under the MIT License.
Authored and maintained by Rico Sta. Cruz with help from contributors.

ricostacruz.com  ·  GitHub @rstacruz  ·  Twitter @rstacruz

Status npm version spm package