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

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

更新:

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

示例和反应加载屏幕。


当前回答

当你的React应用程序是巨大的,它真的需要时间来启动和运行后,页面已经加载。比如,你将应用的React部分挂载到#app上。通常,index.html中的这个元素只是一个空的div:

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

你可以做的是放一些样式和一堆图像,让它在页面加载和初始React应用程序渲染到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>

页面加载后,用户将立即看到index.html的原始内容。不久之后,当React准备好将呈现的组件的整个层次结构挂载到这个DOM节点时,用户将看到实际的应用程序。

注意class,而不是className。这是因为你需要把它放到html文件中。


如果你使用SSR,事情就不那么复杂了,因为用户会在页面加载后立即看到真正的应用程序。

其他回答

在公用文件夹中编辑index.html文件的位置。复制你的图像到相同的位置index.html在公共文件夹。 然后将index.html中包含<div id="root"> </div>标签的部分内容替换为下面给定的html代码。

<div id="root">  <img src="logo-dark300w.png" alt="Spideren" style="vertical-align: middle; position: absolute;
   top: 50%;
   left: 50%;
   margin-top: -100px; /* Half the height */
   margin-left: -250px; /* Half the width */" />  </div>

在加载过程中,Logo现在将出现在页面中间。并将在几秒钟后被React替换。

如果有人正在为上述用例寻找一个插入式、零配置和零依赖的库,请尝试pace.js (https://codebyzach.github.io/pace/docs/)。

它自动挂钩事件(ajax, readyState,历史推送状态,js事件循环等),并显示一个可定制的加载器。

与我们的react/relay项目合作良好(使用react-router, relay请求处理导航更改) (不是affliated;在我们的项目中使用了pace.js,它工作得很好)

你可以通过在react中使用惰性加载轻松做到这一点。 为此你必须使用惰性和悬疑反应。

import React, { lazy, Suspense } from 'react';

const loadable = (importFunc, { fallback = null } = { fallback: null }) => {
  const LazyComponent = lazy(importFunc);

  return props => (
    <Suspense fallback={fallback}>
      <LazyComponent {...props} />
    </Suspense>
  );
};

export default loadable;

然后像这样导出你的组件。

export const TeacherTable = loadable(() =>
  import ('./MainTables/TeacherTable'), {
    fallback: <Loading />,
  });

然后在你的路由文件中像这样使用它。

 <Route exact path="/app/view/teachers" component={TeacherTable} />

这就是现在你很好去每次你的DOM渲染你的加载组件将显示为我们已经在上面的fallback属性中指定。只要确保你只在componentDidMount()中做任何ajax请求

如果你使用react-router来管理你的应用程序的路由,你可以很容易地添加加载屏幕与我做的react-router加载库。

它也会影响页面切换,但我认为,如果你想预装第一页,自然也会预装其他页面。

这个方法和悬疑方法的区别在于,有了这个库,你可以在获取数据的同时继续加载。 基本上,这个方法非常类似于在组件中使用isLoading状态,但是如果您有很多不同的页面,则更容易实现。

使用

在路由器部分,从react-router-loading导入Switch和Route,而不是从react-router-dom导入

import { Switch, Route } from "react-router-loading";

<Switch>
    <Route path="/page1" component={Page1} />
    <Route path="/page2" component={Page2} />
    ...
</Switch>

在切换前必须加载的每条路线上添加加载道具

<Switch>
    // data will be loaded before switching
    <Route path="/page1" component={Page1} loading />

    // instant switch as before
    <Route path="/page2" component={Page2} />
    ...
</Switch>

在加载道具路由中提到的组件的初始加载方法的末尾添加loadingContext.done()(在这种情况下是Page1)

import { LoadingContext } from "react-router-loading";
const loadingContext = useContext(LoadingContext);

const loading = async () => {
    // loading some data

    // call method to indicate that loading is done and we are ready to switch
    loadingContext.done();
};

你可以指定加载屏幕,将显示在你的应用程序的第一次加载

const MyLoadingScreen = () => <div>Loading...</div>

<Switch loadingScreen={MyLoadingScreen}>
...
</Switch>

我不知道现在回答是否太晚,因为你可能已经找到了解决方案,但这里有一个来自我的观点,因为这个问题真的很有用。: 我在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。