You don't need any redux for this...

import {lazy, Suspense} from 'react'
import {BrowserRouter, Switch, Route} from 'react-router-dom'

import Loader from './path/to/loader'

const Component1 = lazy(() => import('./path/to/component1')
const Component2 = lazy(() => import('./path/to/component2')

const Router = () => {
  <Suspense fallback={<Loader/>}>
        <Route path='/path1' component={Component1}/>
        <Route path='/path2' component={Component2}/>

If that doesn't work for you then you'll need to create a parent that can fetch all the data required before rendering and passing it down to children, then you can show the loader in that parent.

If you let a global component manage loading every time a fetch call is made, you'll always end up dealing with that flickering or double loading cascading effect.


here is the project with redux and a single loading

I made a loading reducer and in each component if data need to be fetched ,start-loading is dispatched and a value is pushed into loading array and when data has been fetched, stop-loadig is dispatched and value is popped from array.

const LoadingReducer = (state = initState, action) => {
  const prevState = { ...state };
  switch (action.type) {
    case "START_LOADING":
      return { ...state, prevState };
    case "STOP_LOADING":
      return { ...state, prevState };
      return state;

and in App.js I just get the loading from store and check if it has value or not then decide to show the Loader or not

import { useEffect, useState } from "react";
import { connect } from "react-redux";
import UserRoutes from "./UserRoutes";
import Loader from "./Loader";
import "./styles.css";

const App = (props) => {
  const [loading, setLoading] = useState(0);
  useEffect(() => {
  }, [props.loading]);
  return (
    <div className="App">
      {loading && <Loader />}
      <UserRoutes />
const mapStateToProps = (state) => {
  return {
    loading: state.LoadingReducer.loading.length > 0 ? true : false

export default connect(mapStateToProps, null)(App);


I don't know how is your app structured, but this will give you an idea. You can add a property to your state to control the pending requests.

const STATE = {
 requests: []

Define the basic actions ( You can add more like request cancelled, etc). You need to know when a request starts and when it ends:

const requestStartedAction = id => ({
  payload: { id } //--> something to identify the request

const requestEndedAction = id => ({
  payload: { id }

The reducer:

export default function(state = {}, action) {
  switch (action.type) {
      return {
        requests: [...state.requests,], //-> add a new request to the list
        loading: true,
      const pendingRequests = state.requests.filter(id => id!==; //--> remove request from the list
      return {
        requests: pendingRequests,
        loading: !Boolean(pendingRequests.length), //--> don't hide the loading if there any request pending

Then, every time you make a request you call requestStartedAction. When the request being finished you can call requestEndedAction. Basic example using fetch:

fetch(URL).finally(() => dispatch(requestEndedAction(ID)));

The loading effect will stop if the requests list is empty.

Related Query

More Query from same tag