reactjslazy-loadingreact-suspense

Prevent react suspense hide the content


I have googled, watched lot of videos to implement something like youtube loading as in the screenshot below. So I have route based naviation where I have lazy loads so everything works fine but while loading the content react suspense will make display:none to the components as a result it becomes invisible form the screen and only the fallback component is visible

I want to keep the content visible and I will make a custom fallback component like the youtube.

<Suspense fallback={<div>Loading...</div>}>
    {content}
</Suspense>

enter image description here


Solution

  • So basically all we have to do is, wrap the loader in a component (Loadable here) and load the script using Loadable. This way we can keep existing content visible and it will show a cool loading animation on top. In this example you will have to calculate with dynamically or you can use indeterminant linear progress since we can't find the actual percent of script that had been loaded. (I had added custom classes make to sure to style the according to your need)

    loadable.js

    import React, { Suspense } from 'react';
    
    // this will show the animation
    const Loader = () => {
      return (
        <div className="position-fixed w-100 top-0 start-0 zindex-9999">
          <div style={{width:"{dynamic}%",height:"3px",background:"red"}}/>
        </div>
      );
    };
    
    const Loadable = (Component) => (props) => (
      <Suspense fallback={<Loader />}>
        <Component {...props} />
      </Suspense>
    );
    
    export default Loadable;
    

    Here's how to use in routes.js

    import React, { lazy } from 'react';
    import Loadable from './components/Loadable';
    
    // page import
    const Dashboard = Loadable(lazy(() => import('./pages/dashboard')));
    
    // define routes
    const routes = [
        {
            path: "dashboard",
            element: <DashboardLayout />,
            children: [
                {
                    path: "",
                    element: <Dashboard />,
                },
            ]
        },
    ]