react-redux-loading-bar is a Redux-based loading bar component for React applications. It provides a top-loading bar that automatically shows progress for async operations managed through Redux actions, making it ideal for applications using Redux for state management. This guide walks through advanced usage of react-redux-loading-bar with React and Redux, including middleware integration, custom configurations, and complex loading patterns. This is part 51 of a series on using react-redux-loading-bar with React.
Prerequisites
Before you begin, make sure you have:
- Node.js version 14.0 or higher installed
- npm, yarn, or pnpm package manager
- A React project (version 16.8 or higher) or create-react-app setup
- Redux and React-Redux installed and configured
- Basic knowledge of Redux (actions, reducers, middleware)
- Understanding of React hooks (useSelector, useDispatch)
- Familiarity with async operations and Redux middleware
Installation
Install react-redux-loading-bar and Redux dependencies:
npm install react-redux-loading-bar react-redux redux
Or with yarn:
yarn add react-redux-loading-bar react-redux redux
Or with pnpm:
pnpm add react-redux-loading-bar react-redux redux
After installation, your package.json should include:
{
"dependencies": {
"react-redux-loading-bar": "^5.0.0",
"react-redux": "^8.0.0",
"redux": "^4.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
Project Setup
Set up Redux store with loading bar reducer and middleware. First, create the Redux store:
// src/store/index.js
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { loadingBarReducer } from 'react-redux-loading-bar';
import thunk from 'redux-thunk';
const rootReducer = combineReducers({
loadingBar: loadingBarReducer
});
export const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
Now set up the provider and loading bar component:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './store';
import LoadingBar from 'react-redux-loading-bar';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<LoadingBar />
<App />
</Provider>
</React.StrictMode>
);
First Example / Basic Usage
Let's create a simple loading bar example. Create a new file src/LoadingBarExample.jsx:
// src/LoadingBarExample.jsx
import React from 'react';
import { useDispatch } from 'react-redux';
import { showLoading, hideLoading } from 'react-redux-loading-bar';
function LoadingBarExample() {
const dispatch = useDispatch();
const handleLoad = async () => {
dispatch(showLoading());
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
} finally {
dispatch(hideLoading());
}
};
return (
<div style={{ padding: '20px' }}>
<h2>Loading Bar Example</h2>
<button
onClick={handleLoad}
style={{
padding: '10px 20px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Start Loading
</button>
</div>
);
}
export default LoadingBarExample;
Update your App.jsx:
// src/App.jsx
import React from 'react';
import LoadingBarExample from './LoadingBarExample';
import './App.css';
function App() {
return (
<div className="App">
<LoadingBarExample />
</div>
);
}
export default App;
Understanding the Basics
react-redux-loading-bar uses Redux for state management:
- loadingBarReducer: Redux reducer that manages loading state
- showLoading action: Dispatches to show the loading bar
- hideLoading action: Dispatches to hide the loading bar
- LoadingBar component: Renders the loading bar UI
- Middleware integration: Can integrate with Redux middleware for automatic loading
Key concepts for advanced usage:
- Redux Integration: Loading state is managed through Redux store
-
Action Dispatching: Use
showLoadingandhideLoadingactions - Middleware: Integrate with Redux middleware for automatic loading bar management
- Multiple Requests: Handles multiple concurrent requests
- Customization: Styling and behavior can be customized
Here's an example with middleware integration:
// src/store/index.js
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { loadingBarReducer } from 'react-redux-loading-bar';
import thunk from 'redux-thunk';
// Custom middleware for automatic loading bar
const loadingBarMiddleware = store => next => action => {
if (action.type.endsWith('_PENDING')) {
store.dispatch({ type: 'SHOW_LOADING_BAR' });
} else if (action.type.endsWith('_FULFILLED') || action.type.endsWith('_REJECTED')) {
store.dispatch({ type: 'HIDE_LOADING_BAR' });
}
return next(action);
};
const rootReducer = combineReducers({
loadingBar: loadingBarReducer
});
export const store = createStore(
rootReducer,
applyMiddleware(thunk, loadingBarMiddleware)
);
Practical Example / Building Something Real
Let's build a comprehensive loading system with Redux actions and middleware:
// src/actions/loadingActions.js
import { showLoading, hideLoading } from 'react-redux-loading-bar';
export const startLoading = () => (dispatch) => {
dispatch(showLoading());
};
export const stopLoading = () => (dispatch) => {
dispatch(hideLoading());
};
export const fetchData = () => async (dispatch) => {
dispatch(showLoading());
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
return data;
} catch (error) {
dispatch({ type: 'FETCH_DATA_ERROR', payload: error.message });
throw error;
} finally {
dispatch(hideLoading());
}
};
Create a component that uses the loading bar:
// src/AdvancedLoadingSystem.jsx
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { showLoading, hideLoading } from 'react-redux-loading-bar';
import LoadingBar from 'react-redux-loading-bar';
function AdvancedLoadingSystem() {
const dispatch = useDispatch();
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const handleSingleRequest = async () => {
dispatch(showLoading());
try {
await new Promise(resolve => setTimeout(resolve, 2000));
setData('Single request completed');
} catch (err) {
setError(err.message);
} finally {
dispatch(hideLoading());
}
};
const handleMultipleRequests = async () => {
dispatch(showLoading());
try {
// Simulate multiple concurrent requests
await Promise.all([
new Promise(resolve => setTimeout(resolve, 1000)),
new Promise(resolve => setTimeout(resolve, 1500)),
new Promise(resolve => setTimeout(resolve, 2000))
]);
setData('Multiple requests completed');
} catch (err) {
setError(err.message);
} finally {
dispatch(hideLoading());
}
};
const handleSequentialRequests = async () => {
dispatch(showLoading());
try {
await new Promise(resolve => setTimeout(resolve, 1000));
await new Promise(resolve => setTimeout(resolve, 1000));
await new Promise(resolve => setTimeout(resolve, 1000));
setData('Sequential requests completed');
} catch (err) {
setError(err.message);
} finally {
dispatch(hideLoading());
}
};
return (
<div style={{ padding: '20px' }}>
<LoadingBar
style={{
backgroundColor: '#007bff',
height: '3px',
zIndex: 9999
}}
showFastActions
/>
<h1>Advanced Loading System</h1>
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px', maxWidth: '400px' }}>
<button
onClick={handleSingleRequest}
style={{
padding: '10px 20px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Single Request
</button>
<button
onClick={handleMultipleRequests}
style={{
padding: '10px 20px',
backgroundColor: '#28a745',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Multiple Requests
</button>
<button
onClick={handleSequentialRequests}
style={{
padding: '10px 20px',
backgroundColor: '#ffc107',
color: 'black',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Sequential Requests
</button>
</div>
{data && (
<div style={{
marginTop: '20px',
padding: '15px',
backgroundColor: '#d4edda',
color: '#155724',
borderRadius: '4px'
}}>
{data}
</div>
)}
{error && (
<div style={{
marginTop: '20px',
padding: '15px',
backgroundColor: '#f8d7da',
color: '#721c24',
borderRadius: '4px'
}}>
Error: {error}
</div>
)}
</div>
);
}
export default AdvancedLoadingSystem;
Create a custom hook for loading management:
// src/hooks/useLoadingBar.js
import { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { showLoading, hideLoading } from 'react-redux-loading-bar';
export const useLoadingBar = () => {
const dispatch = useDispatch();
const withLoading = useCallback(async (asyncFn) => {
dispatch(showLoading());
try {
const result = await asyncFn();
return result;
} finally {
dispatch(hideLoading());
}
}, [dispatch]);
const startLoading = useCallback(() => {
dispatch(showLoading());
}, [dispatch]);
const stopLoading = useCallback(() => {
dispatch(hideLoading());
}, [dispatch]);
return {
withLoading,
startLoading,
stopLoading
};
};
Update your store with proper configuration:
// src/store/index.js
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { loadingBarReducer } from 'react-redux-loading-bar';
import thunk from 'redux-thunk';
const rootReducer = combineReducers({
loadingBar: loadingBarReducer
});
export const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
Update your App.jsx:
// src/App.jsx
import React from 'react';
import AdvancedLoadingSystem from './AdvancedLoadingSystem';
import './App.css';
function App() {
return (
<div className="App">
<AdvancedLoadingSystem />
</div>
);
}
export default App;
This example demonstrates:
- Redux-based loading bar
- Single and multiple request handling
- Sequential request management
- Custom loading hook
- Error handling with loading bar
- Custom styling
Common Issues / Troubleshooting
Loading bar not appearing: Ensure
LoadingBarcomponent is rendered in your app andloadingBarReduceris added to your Redux store. Also make sure you're dispatchingshowLoadingactions.Redux store not configured: Make sure you've added the
loadingBarReducerto your Redux store usingcombineReducers. The reducer must be namedloadingBar.Actions not working: Ensure you're using
useDispatchfromreact-reduxto dispatch actions. ImportshowLoadingandhideLoadingfromreact-redux-loading-bar.Loading bar not hiding: Make sure you're calling
hideLoading()in afinallyblock or after the async operation completes. If an error occurs, the loading bar should still be hidden.Multiple requests: react-redux-loading-bar handles multiple concurrent requests automatically. It shows the bar when any request starts and hides it when all requests complete.
Styling issues: Use the
styleprop on theLoadingBarcomponent to customize appearance. You can setbackgroundColor,height,zIndex, and other CSS properties.
Next Steps
Now that you have an advanced understanding of react-redux-loading-bar:
- Explore middleware integration for automatic loading
- Learn about custom loading bar configurations
- Implement loading bar with Redux Saga
- Add loading bar to API interceptors
- Integrate with React Router for route-based loading
- Learn about other loading bar libraries
- Check the official repository: https://github.com/mironov/react-redux-loading-bar
- Look for part 52 of this series for more advanced topics
Summary
You've successfully integrated react-redux-loading-bar into your React application with Redux for advanced loading bar management. react-redux-loading-bar provides a Redux-based solution for displaying loading progress with automatic handling of multiple concurrent requests.
SEO Keywords
react-redux-loading-bar
React Redux loading bar
react-redux-loading-bar tutorial
React loading indicator
react-redux-loading-bar installation
React Redux loading
react-redux-loading-bar example
React progress bar
react-redux-loading-bar setup
React Redux middleware
react-redux-loading-bar customization
React loading state
react-redux-loading-bar actions
React Redux library
react-redux-loading-bar getting started
Top comments (0)