Implementing a React Progress Bar Managed Through Redux
Using <TopBarProgress /> for easy progress bar mounting

React apps are static, therefore any update made to the data being displayed will involve a fetch request to a backend service (or incoming data packets from an open socket connection), but in this brief moment the app will be waiting for that data to return to the client. A progress bar is needed — which can easily be linked with your Redux state management to either show or hide the progress bar. In this article we will be visiting how this is implemented in React.
A Little About Progress Bars
A progress bar is a singleton and should only be mounted once within your DOM. This makes sense since there is only one App object — e.g. there are not multiple apps running in one browser window. In the event that the browser is split into two or more isolated UIs, there may be a use case for multiple progress bars, although this scenario is probably only likely for complex CMSs — and then you would probably opt for loader animations within that UI space.
Progress bars are typically fixed at the top of the client’s browser window and animate in various ways to indicate that the page is waiting for something to happen.
React TopBar Progress Indicator
For this article we will be using the React TopBar Progress Indicator package, found at the following NPMJS url:
https://www.npmjs.com/package/react-topbar-progress-indicator
For such a small component it is rather popular, peaking at around 15,000 weekly downloads at the time of this writing.
Install it with the following NPM command:
npm install react-topbar-progress-indicator
Our project is now ready to handle this handy UI component.
This component works in a very simple manor. If we mount it, e.g. render it’s component, the bar will appear and start to animate. If we unmount it, it will complete its animation and fade out.
What animation to use?
The animation this component adopts is a rather basic width expansion that incremently slows down until it is crawling at a snails pace. Upon unmounting the progress bar, it quickly snaps to a 100% width and fades out. This is one type of progress animation — you may notice websites like Medium opt for a continuous fast-paced loader that loops until the representative task is completed. This faster paced animation may give you the perception that your page loaded faster — but the style of animation is ultimately up to you.
Back to our progress bar. We can invoke it with the <TopBarProgress />
component within a component’s render:
import TopBarProgress from "react-topbar-progress-indicator";... render() {
return(<TopBarProgress />)
}...
Pretty simple, right? We can expand this and link it to a Redux setup. How would we quickly and efficiently do this?
- Create a ProgressBar.js component that passes the status of the progress bar from Redux into the component. This will determine whether the progress bar is mounted.
- Import ProgressBar.js into App.js (your top-most component) and render it on every page load.
- Configure Redux action and reducer.
Within other components, import a Redux action, e.g.handleProgressBar
, with anisOpen
boolean which will determine open or closed.
Configure a reducer to update your app state whenhandleProgressBar
is called.
Let’s go through these steps.
1. Configuring ProgressBar.js
Below is the complete ProgressBar script for this example, whose responsibility is to mount or unmount the <TopProgressBar />
component. Let’s take a look at this script:
As you can see, Redux has been imported, and is passing the status of my progress bar from state.ui.progressBarStatus
. This is done within a container component named HandleProgressBar. From here, we either render <TopProgressBar />
or not in our presentational component render.
2. Importing ProgressBar into App.js
As I mentioned above, your progress bar will be present throughout your entire app, therefore it should be placed outside of your navigation — maybe a React Router Switch config. For visual clarity, this is how we would place our ProgressBar:
...
import { HandleProgressBar } from "./ProgressBar";
class App extends Component {render() { const { cookies } = this.props; return (
<div>
<HandleProgressBar />
<Switch>
<Route />
<Route />
</Switch>
</div>
)
}
Remember, there cannot be 2 top-most components, therefore we wrap the progress bar and routing in a parent <div>
element. Now our progress bar is ready to be toggled.
3. Configuring Redux Action and Reducer
Adding a boolean to a Redux state tree is straight forward, so let’s quickly visit how this is done for the progress bar, starting with an action:
actions/index.js:
...export const setProgressBar = (isOpen) => (
{
type: 'SET_PROGRESS_BAR',
isOpen: isOpen
});...
My SET_PROGRESS_BAR
action is responsible for passing the isOpen
bool to my reducer.
reducers/ui.js:
export const ui = (state = {}, action) => { switch (action.type) { case 'SET_PROGRESS_BAR':
return Object.assign({}, state, { progressBarStatus: action.isOpen });
default:
return state;
}
};export default ui
And this is our progress bar setup in its entirety.
Bar Style
We also have access to some bar styling options, all documented from the Config section of the package’s NPMJS page. The ability to add multiple colours adds personalisation to the bar, in addition to shadow, shadow blur and thickness options.