5

I am trying to implement an application that has 10-15 pages. That works with react-router well but I should use react-loadable to have a Spinner and loading effect ...

But how can I import router components inside the loadable ?

I should create one const variable for each component ?

Like this :

const Home = Loadable({
    loader: () => import('./Home'),
    loading: Loading,
});

const News = Loadable({
    loader: () => import('./News'),
    loading: Loading,
});

const Gallery = Loadable({
    loader: () => import('./Gallery'),
    loading: Loading,
});

class App extends React.Component {
    render() {
        return (
          <Router>
              <Route exact path="/" component={Home} />
              <Route path="/news" component={News} />
              <Route path="/gallery" component={Gallery} />
          </Router>
        )
    }
}

Or it's possible with other tricks ?

1 Answer 1

1

This is a bit tricky. You don't need to use react-loadable.

Demo here.

If you want to make loader for images and other components until they are onLoad, you can use react-content-loader instead to create skeleton screens (See components/Image.js in demo). It could make "almost" perfect loader. So far, this is what I can do. I have no idea to detect onLoad for css :(

You can create a new file named routes.js which includes all pages.

- /src
-- /pages
--- Gallery.js
--- Home.js
--- News.js
--- withBase.js
-- App.js
-- routes.js

routes.js

import Home from './pages/Home';
import Gallery from './pages/Gallery';
import News from './pages/News';
// Add as much as you want...

export default [
   {
       path: '/',
       component: Home,
   },
   {
       path: '/gallery',
       component: Gallery,
   },
   {
       path: '/news',
       component: News,
   },
];

You need to create a high order component that will wrap each page.

withBase.js (HOC)

import React from "react";

export default WrappedComponent =>
  class extends React.Component {
    state = {
      isLoading: true
    };

    componentDidMount() {
      this.hideLoader();
    }

    hideLoader = () => {
      // This is for demo purpose
      const proc = new Promise(resolve => {
        setTimeout(() => resolve(), 3000);
      });
      proc.then(() => this.setState({ isLoading: false }));
    };

    render() {
      return (
        <div>
          {this.state.isLoading ? <p>Loading...</p> : <WrappedComponent />}
        </div>
      );
    }
  };

Usage: e.g. export default withBase(Home).

Then, in App.js just loop the routes.

    <Switch>
      {routes.map(route => (
        <Route
          exact
          key={route.path}
          path={route.path}
          component={route.component}
        />
      ))}
    </Switch>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, it's a cute trick ! but this check only componentDidMount() and the loading not be real (for all images, css, js etc. ) ... can I use something like window.onload() to check even images or other assets and implement a perfect loading ?!
You might be interested with skeleton screens. I can make a simple demo later, if you are pleased to wait.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.