'How to get loading progress in React.lazy and Suspense

I'm using lazy to split my routes and I wanna know if there is any way I can get the loading progress in lazy and suspense.

Currently I'm using it like this.

const Home = lazy(() => import("./Home"));
const About = lazy(() => import("./About"));

function App() {
  return (
    <Router>
      <Switch>
        <Suspense fallback={<div>loading</div>}>
          <Route path="/" exact={true} component={Home} />
          <Route path="/About" component={About} />
        </Suspense>
      </Switch>
    </Router>
  );
}

■ But I want to show the loading progress (like youtube).
■ Is there any way I can retrieve the progress for example like below.

<Suspense fallback={({progress}) => <LoadingBar progress={progress}/>}>


Solution 1:[1]

This is my solution:

const LazyLoad = () => {
    useEffect(() => {
        NProgress.start();

        return () => {
            NProgress.stop();
        };
    });

    return '';
};

<Suspense fallback={<LazyLoad />}>

Solution 2:[2]

lazy uses JavaScript promises which either resolve or reject, but they don't report any progress.

You can however fake the progress with something like http://ricostacruz.com/nprogress/ which increments the progress bar randomly.

Solution 3:[3]

The javascript way

Install nprogress

npm i nprogress

Import CSS globaly

you may customize the nprogress layout in your global css to make it suitable for your website

import "nprogress/nprogress.css"

React lazy uses promise to suspense its component so we can use it to control our nprogress package

Lazy -----> Promise ----> resolve ----> render

here is how to do it

const MyPage = React.lazy(() => mew Promise(
    (resolve, reject) => {
         NProgress.start()

         import("path/to/page").then(() => {
              NProgress.done()
              resolve(module)

        }).catch(err) => {
            NProgress.done()
            reject(err)

         })

    })
)

then you can wrap it into a suspense component and add a loading.

<Route path="/" exact={true} component={
    {/* i use a custom loading component (dot animations) */}
    <Suspense fallback={() => "..."}>
       <MyPage />
    </Suspense>
</Route>

this would be a close example of what you want, however you can't make the loading as real as the promise itself. usually others use this solution aswell, so don't overthink it and leave it as is

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tung Luong Thanh
Solution 2 amann
Solution 3