React - Display loading screen while DOM is rendering?

前端 未结 19 1586
我在风中等你
我在风中等你 2020-11-28 00:29

This is an example from Google Adsense application page. The loading screen displayed before the main page showed after.

I don\'t know how to do the same th

相关标签:
19条回答
  • 2020-11-28 00:47

    You don't need that much effort, here's a basic example.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8" />
      <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <meta name="theme-color" content="#000000" />
      <meta name="description" content="Web site created using create-react-app" />
      <link rel="apple-touch-icon" href="logo192.png" />
      <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
      <title>Title</title>
      <style>
        body {
          margin: 0;
        }
    
        .loader-container {
          width: 100vw;
          height: 100vh;
          display: flex;
          overflow: hidden;
        }
    
        .loader {
          margin: auto;
          border: 5px dotted #dadada;
          border-top: 5px solid #3498db;
          border-radius: 50%;
          width: 100px;
          height: 100px;
          -webkit-animation: spin 2s linear infinite;
          animation: spin 2s linear infinite;
        }
    
        @-webkit-keyframes spin {
          0% {
            -webkit-transform: rotate(0deg);
          }
    
          100% {
            -webkit-transform: rotate(360deg);
          }
        }
    
        @keyframes spin {
          0% {
            transform: rotate(0deg);
          }
    
          100% {
            transform: rotate(360deg);
          }
        }
    
      </style>
    </head>
    
    <body>
      <noscript>You need to enable JavaScript to run this app.</noscript>
      <div id="root">
        <div class="loader-container">
          <div class="loader"></div>
        </div>
      </div>
    </body>
    
    </html>
    

    You can play around with HTML and CSS to make it looks like your example.

    0 讨论(0)
  • 2020-11-28 00:51

    I'm also using React in my app. For requests I'm using axios interceptors, so great way to make loader screen (fullpage as you showed an example) is to add class or id to for example body inside interceptors (here code from official documentation with some custom code):

    // Add a request interceptor
    axios.interceptors.request.use(function (config) {
        // Do something before request is sent
         document.body.classList.add('custom-loader');
         return config;
      }, function (error) {
        // Do something with request error
        return Promise.reject(error);
      });
    
    // Add a response interceptor
    axios.interceptors.response.use(function (response) {
        // Do something with response data
           document.body.classList.remove('custom-loader');
           return response;
      }, function (error) {
        // Do something with response error
        return Promise.reject(error);
      }); 
    

    And then just implement in CSS your loader with pseudo-elements (or add class or id to different element, not body as you like) - you can set color of background to opaque or transparent, etc... Example:

    custom-loader:before {
        background: #000000;
        content: "";
        position: fixed;
        ...
    }
    
    custom-loader:after {
        background: #000000;
        content: "Loading content...";
        position: fixed;
        color: white;
        ...
    }
    
    0 讨论(0)
  • 2020-11-28 00:51

    I also used @Ori Drori's answer and managed to get it to work. As your React code grows, so will the bundles compiled that the client browser will have to download on first time access. This imposes a user experience issue if you don't handle it well.

    What I added to @Ori answer was to add and execute the onload function in the index.html on onload attribute of the body tag, so that the loader disappear after everything has been fully loaded in the browse, see the snippet below:

    <html>
      <head>
         <style>
           .loader:empty {
              position: absolute;
              top: calc(50% - 4em);
              left: calc(50% - 4em);
              width: 6em;
              height: 6em;
              border: 1.1em solid rgba(0, 0, 0, 0.2);
              border-left: 1.1em solid #000000;
              border-radius: 50%;
              animation: load8 1.1s infinite linear;
            }
            @keyframes load8 {
              0% {
               transform: rotate(0deg);
              }
              100% {
               transform: rotate(360deg);
              }
            }
         </style>
         <script>
           function onLoad() {
             var loader = document.getElementById("cpay_loader");loader.className = "";}
         </script>
       </head>
       <body onload="onLoad();">
         more html here.....
       </body>
    </html>
    
    0 讨论(0)
  • 2020-11-28 00:51

    this is my implementation, based on the answers

    ./public/index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <title>React App</title>
      <style>
        .preloader {
          display: flex;
          justify-content: center;
        }
    
        .rotate {
          animation: rotation 1s infinite linear;
        }
    
        .loader-hide {
          display: none;
        }
    
        @keyframes rotation {
          from {
            transform: rotate(0deg);
          }
    
          to {
            transform: rotate(359deg);
          }
        }
      </style>
    </head>
    
    <body>
      <div class="preloader">
        <img src="https://i.imgur.com/kDDFvUp.png" class="rotate" width="100" height="100" />
      </div>
      <div id="root"></div>
    </body>
    
    </html>
    

    ./src/app.js

    import React, { useEffect } from "react";
    
    import "./App.css";
    
    const loader = document.querySelector(".preloader");
    
    const showLoader = () => loader.classList.remove("preloader");
    const addClass = () => loader.classList.add("loader-hide");
    
    const App = () => {
      useEffect(() => {
        showLoader();
        addClass();
      }, []);
      return (
        <div style={{ display: "flex", justifyContent: "center" }}>
          <h2>App react</h2>
        </div>
      );
    };
    
    export default App;
    
    
    0 讨论(0)
  • 2020-11-28 00:56

    When your React app is massive, it really takes time for it to get up and running after the page has been loaded. Say, you mount your React part of the app to #app. Usually, this element in your index.html is simply an empty div:

    <div id="app"></div>
    

    What you can do instead is put some styling and a bunch of images there to make it look better between page load and initial React app rendering to DOM:

    <div id="app">
      <div class="logo">
        <img src="/my/cool/examplelogo.svg" />
      </div>
      <div class="preload-title">
        Hold on, it's loading!
      </div>
    </div>
    

    After the page loads, user will immediately see the original content of index.html. Shortly after, when React is ready to mount the whole hierarchy of rendered components to this DOM node, user will see the actual app.

    Note class, not className. It's because you need to put this into your html file.


    If you use SSR, things are less complicated because the user will actually see the real app right after the page loads.

    0 讨论(0)
  • 2020-11-28 00:57

    This could be done by placing the loading icon in your html file (index.html for ex), so that users see the icon immediately after the html file has been loaded.

    When your app finishes loading, you could simply remove that loading icon in a lifecycle hook, I usually do that in componentDidMount.

    0 讨论(0)
提交回复
热议问题