How to get loading progress in React.lazy and Suspense
Asked Answered
D

4

13

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}/>}>
Discretionary answered 24/1, 2019 at 2:54 Comment(2)
good question :)Eugene
I was looking for something similar, Also I want to keep the content visible while Suspense is working. Here's my question #71663577Oshea
T
5

This is my solution:

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

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

    return '';
};

<Suspense fallback={<LazyLoad />}>
Teodorateodorico answered 2/6, 2020 at 9:13 Comment(1)
It is always helpful add some explanation to your answer, to make it more clear and understandable. Please read stackoverflow.com/help/how-to-answer.Sideboard
S
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.

Strongwilled answered 14/5, 2019 at 14:50 Comment(0)
P
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>
Perseus answered 4/6, 2023 at 17:30 Comment(0)
C
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

Counterbalance answered 24/4, 2022 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.