I tried @bprogress/react which allows for easy integration of progress bars in React apps
This page has been translated by machine translation. View original
Web apps often need to show a "I'm loading something, please wait" message during page transitions or data fetching, right?
@bprogress/react allows you to easily integrate progress bars into React apps without depending on a specific router.
After trying it out, I found it had more flexibility than I expected, so I'd like to introduce it.
First, try out the StackBlitz demo.
Click Fetch data and you'll see a bar run across the top for 2 seconds, giving the impression of loading.
What is @bprogress/react?
@bprogress/react is a TypeScript-based progress bar library built on NProgress.
What makes it distinctive is that it's router-independent.
While libraries like next-nprogress-bar for Next.js automatically hook into router events, @bprogress/react is designed for you to manually call start() / stop() using the useProgress hook. There's also a useAnchorProgress hook for those who want automatic behavior, but the library is fundamentally built for manual control.
There are dedicated packages for Next.js, Remix, and Vue in addition to React.
Installation
npm install @bprogress/react
# or
pnpm add @bprogress/react
Basic Usage
1. Wrap your app with ProgressProvider
Place ProgressProvider at the root of your app. Setting disableStyle disables the default styles, allowing you to fully control custom styles with the css() function (discussed later).
import { ProgressProvider } from '@bprogress/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<ProgressProvider disableStyle>
<App />
</ProgressProvider>
</React.StrictMode>
);
- Reference: ProgressProvider - BProgress
2. Control the bar with the useProgress hook
Control the bar with start() / stop() / pause() / resume() returned by the useProgress hook.
import { useProgress } from '@bprogress/react';
function App() {
const { start, stop, pause, resume } = useProgress();
return (
<div>
<button onClick={() => start()}>start()</button>
<button onClick={() => stop()}>stop()</button>
<button onClick={() => pause()}>pause()</button>
<button onClick={() => resume()}>resume()</button>
</div>
);
}
- Reference: useProgress - BProgress
It's very simple. When combining with API fetching, it looks like this:
const { start, stop } = useProgress();
const handleFetch = async () => {
start();
await fetchData();
stop();
};
Features in the Demo
The demo I created allows you to interactively toggle the following options:
| Item | Description |
|---|---|
| Basic controls | Manually call start() / stop() / pause() / resume() |
| Simulated fetch | Simulate API fetching with start() → 2-second wait → stop() |
| Color | Select bar color from Blue / Green / Pink / Orange |
| Height | Select bar thickness from 2px / 3px / 4px / 6px |
| Speed | Select animation speed from Slow / Normal / Fast |
| Easing | Animation transition function (linear / ease / ease-in-out / cubic-bezier) |
| Spinner | Toggle spinner visibility and position (4 corners) |
| Direction | Direction the bar extends (LTR(Left To Right) / RTL(Right To Left)) |
| Trickle | Toggle the "trickle" feature that automatically advances the bar and its speed |
Customization Methods
Change options dynamically with setOptions()
Use setOptions() returned by useProgress to change options at runtime.
const { setOptions } = useProgress();
// Change animation speed
setOptions({ speed: 800 });
// Change easing
setOptions({ easing: "cubic-bezier(0.34, 1.56, 0.64, 1)" });
// Show spinner
setOptions({ showSpinner: true });
// Switch to RTL mode
setOptions({ direction: "rtl" });
// Disable trickle (automatic progress)
setOptions({ trickle: false });
- Reference: useProgress - BProgress
- Reference: configure()
Change styles dynamically with css() function
The css() function from @bprogress/core generates a CSS string with color, height, and spinner position settings. By injecting this into a <style> tag, you can change all styles at once.
import { css } from "@bprogress/core";
import type { SpinnerPosition } from "@bprogress/react";
function applyProgressCss(
color: string,
height: string,
spinnerPosition: SpinnerPosition,
) {
const id = "bprogress-custom";
let el = document.getElementById(id) as HTMLStyleElement | null;
if (!el) {
el = document.createElement("style");
el.id = id;
document.head.appendChild(el);
}
el.textContent = css({ color, height, spinnerPosition });
}
// Change color, height, and spinner position at once
applyProgressCss("#22c55e", "4px", "top-right");
- Reference: CSS - BProgress
Conclusion
I tried @bprogress/react and liked its simple design where you just call the useProgress hook without router dependencies.
It seems useful for lightly indicating loading states.
There are dedicated packages for Next.js and Remix, so consider those if you're using one of those frameworks.