Prevent react suspense hide the content
Asked Answered
P

2

6

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

Pictorial answered 29/3, 2022 at 13:36 Comment(0)
P
2

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 />,
            },
        ]
    },
]
Pictorial answered 9/7, 2022 at 4:35 Comment(0)
L
1

@Ashiq Dey's suggestion works perfectly. If you use router then instead of wrapping each route in the loadable wrap only the router comp

App.js

const MyRouter = Loadable(lazy(() => import("./Routes/MyRouter")));

return (
    <Provider store={store}>
        <MyRouter/>
    </Provider>
);

MyRouter.js

import { useSelector } from 'react-redux';
import { createBrowserRouter, createRoutesFromElements } from 'your-routing-library';
import { RouterProvider, Route } from 'your-router-components';
import { Path } from 'your-path-constants';

export default function MyRouter() {
    const publicRoutes = Path.public.map((route) => (
        <Route key={route.path} path={route.path} element={<PublicLayout component={route.component} />} />
    ));

    return <RouterProvider router={createBrowserRouter(createRoutesFromElements(publicRoutes))} />;
}

Locally answered 23/12, 2023 at 9:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.