12

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}/>}>
Thu San
  • 1,400
  • 1
  • 17
  • 29
  • good question :) – bitten Feb 17 '19 at 22:12
  • I was looking for something similar, Also I want to keep the content visible while Suspense is working. Here's my question https://stackoverflow.com/questions/71663077/prevent-react-suspense-hide-the-content/71663305 – Ashiq Dey Mar 29 '22 at 13:55

4 Answers4

5

This is my solution:

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

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

    return '';
};

<Suspense fallback={<LazyLoad />}>
Tung Luong Thanh
  • 377
  • 6
  • 11
  • 7
    It is always helpful add some explanation to your answer, to make it more clear and understandable. Please read https://stackoverflow.com/help/how-to-answer. – 32cupo Jun 02 '20 at 09:35
3

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.

amann
  • 5,449
  • 4
  • 38
  • 46
1

Create a Progress Component. This component uses useEffect to start progress and then stops the progress when react destroys the component.

import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { useEffect } from "react";

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

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

    return (
        <div className="grid min-h-screen animate-pulse place-content-center text-6xl text-white">
            Loading...
        </div>
    );
};

export default Progress;

Use this component with react suspense

<Suspense fallback={<Progress />}>
  <App />
</Suspense>
wizAmit
  • 310
  • 1
  • 8
0

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

Ali
  • 615
  • 10
  • 16