这是一个来自谷歌Adsense应用页面的例子。加载界面显示在主界面之前。

我不知道如何用React做同样的事情,因为如果我用React组件渲染加载屏幕,它不会在页面加载时显示,因为它必须等待DOM渲染之前。

更新:

我通过将屏幕加载器放在index.html中并在React componentDidMount()生命周期方法中删除它来举例说明我的方法。

示例和反应加载屏幕。


当前回答

我不知道现在回答是否太晚,因为你可能已经找到了解决方案,但这里有一个来自我的观点,因为这个问题真的很有用。: 我在scrimba.com上上了一堂课,在这里,老师从课堂开始,然后开始讲课。他通过课堂和状态来教授API调用。这是他的代码:

import React, {Component} from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {
            loading: false,
            character: {}
        }
    }
    
    componentDidMount() {
        this.setState({loading: true})
        fetch("https://swapi.dev/api/people/1/")
            .then(response => response.json())
            .then(data => {
                this.setState({
                    loading: false,
                    character: data
                })
            })
    }
    
    render() {
        const text = this.state.loading ? "loading..." : this.state.character.name
        return (
            <div>
                <p>{text}</p>
            </div>
        )
    }
}

export default App

这很直接,在开始时将加载状态设置为true并保持它,直到接收到数据,然后当接收到数据时,更改状态并将加载设置为false并显示内容。 现在我试着用钩子,作为练习,它工作得很顺利!一个简单而有效的解决方案。这是我的代码:

import React, {useState,useEffect} from 'react'

function App()
{
    const [response, setResponse] = useState([]);
    
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        fetchResponse() ;
    } , []);

    const fetchResponse = async () => {
        const data = await fetch("https://swapi.dev/api/people/1/");
        const response = await data.json();

        setResponse(response);
        console.log(response.name);
        setLoading(false);
    } 

        const content = loading ? <i className="fas fa-atom fa-spin"></i> : <h1>{response.name}</h1>

    return(
        <section id="w-d-p">
            {content}
        </section>
    )
}

export default App;

钩子也是一样的逻辑。在数据加载时,我得到了漂亮的转轮然后,我的数据!

哦,顺便说一下,如果你不喜欢这个XD,你可以在fetch中放入自己的API。

其他回答

这可以通过在html文件(例如index.html)中放置加载图标来实现,这样用户就可以在html文件加载后立即看到图标。

当你的应用程序完成加载时,你可以简单地删除生命周期钩子中的加载图标,我通常在componentDidMount中这样做。

这是我基于答案的实现

/公共/ 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;

在componentDidMount中设置超时工作,但在我的应用程序中,我收到了内存泄漏警告。试试这样的方法。

constructor(props) {
    super(props)
    this.state = { 
      loading: true,
    }
  }
  componentDidMount() {
    this.timerHandle = setTimeout(() => this.setState({ loading: false }), 3500); 
  }

  componentWillUnmount(){
    if (this.timerHandle) {
      clearTimeout(this.timerHandle);
      this.timerHandle = 0;
    }
  }

你不需要那么多的努力,这里有一个基本的例子。

<!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>

您可以使用HTML和CSS使其看起来像您的示例。

这将发生在ReactDOM.render()控制根目录<div>之前。也就是说,你的应用程序到那时还没有被安装。

所以你可以把你的加载器添加到index.html文件的根目录<div>。在React接管之前,这将在屏幕上可见。

您可以使用任何最适合您的加载器元素(例如带有动画的svg)。

您不需要在任何生命周期方法上删除它。React会用你渲染的<App/>替换它的根<div>的所有子元素,就像我们在下面的动图中看到的那样。

关于CodeSandbox的例子

index . html

<head>
  <style>
    .svgLoader {
      animation: spin 0.5s linear infinite;
      margin: auto;
    }
    .divLoader {
      width: 100vw;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
  </style>
</head>

<body>
  <div id="root">
    <div class="divLoader">
      <svg class="svgLoader" viewBox="0 0 1024 1024" width="10em" height="10em">
        <path fill="lightblue"
          d="PATH FOR THE LOADER ICON"
        />
      </svg>
    </div>
  </div>
</body>

index.js

在ReactDOM.render()运行之前,使用调试器检查页面。

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

debugger; // TO INSPECT THE PAGE BEFORE 1ST RENDER

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);