programing

반응 - DOM 렌더링 중에 로드 화면을 표시하시겠습니까?

testmans 2023. 3. 1. 09:41
반응형

반응 - DOM 렌더링 중에 로드 화면을 표시하시겠습니까?

이것은 Google Adsense 어플리케이션 페이지의 예입니다.메인 페이지가 표시되기 전에 로딩 화면이 표시됩니다.

여기에 이미지 설명 입력

리액트 컴포넌트에 의해 렌더링된 로딩 화면을 만들면 이전에 렌더링된 DOM을 기다려야 하기 때문에 페이지 로드 중에 표시되지 않기 때문에 리액트에서도 같은 작업을 할 수 없습니다.

갱신일 :

로더를 는는에 넣어 나의 접근 했다.index.html에서 제거합니다.componentDidMount()라이프 사이클 방식

예시리액트 로딩 화면.

목표

html 페이지가 렌더링되면 즉시(React가 로드되는 동안) 스피너를 표시하고 React가 준비되면 페이지를 숨깁니다.

스피너는 순수 HTML/CSS(React 도메인 외부)로 렌더링되므로 React는 표시/숨김 프로세스를 직접 제어하지 않아야 하며 구현은 React에 대해 투명해야 합니다.

솔루션 1 - : 빈 의사 클래스

에 DOM 컨테이너는 다음과 .<div id="app"></div>수 리액션이 반응이 로드되어 렌더링되면 스피너는 사라집니다.

요소수 .DOM 요소(div)는 리액트 루트 내에 추가할 수 없습니다.가 DOM 요소(div 등)의 입니다.리액트는 컨테이너의 내용을 즉시 치환하기 때문입니다.ReactDOM.render()출됩하다null 그 은 '그러면 안 돼요'라는<!-- react-empty: 1 -->, 마운트되어 있는 되고 있지만 경우 」 「 」 「 」 「 」<div id="app"><div class="loader"></div></div>예를 들어)는 동작하지 않습니다.

회피책은 스피너 클래스를 반응 컨테이너에 추가하고 의사 클래스를 사용하는 것입니다.스피너는 컨테이너에 렌더링되지 않는 한 표시됩니다(댓글은 포함되지 않습니다).react가 주석 이외의 다른 내용을 렌더링하는 즉시 로더가 사라집니다.

예 1

에서는, 「이러다」를 렌더링 할 수 있습니다.null컨테이너이기도 합니다.<div id="app" class="app"></div>로더의 클래스는, 다음의 경우에 한해 동작합니다.:empty(예:

class App extends React.Component {
  state = {
    loading: true
  };

  componentDidMount() {
    // this simulates an async action, after which the component will render the content
    demoAsyncCall().then(() => this.setState({ loading: false }));
  }
  
  render() {
    const { loading } = this.state;
    
    if(loading) { // if your component doesn't have to wait for an async action, remove this block 
      return null; // render null when app is not ready
    }
    
    return (
      <div>I'm the app</div>
    ); 
  }
}

function demoAsyncCall() {
  return new Promise((resolve) => setTimeout(() => resolve(), 2500));
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
.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);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>

<div id="app" class="loader"></div> <!-- add class loader to container -->

예 2

「 」의 :empty셀렉터를 표시하거나 숨기기 위한 의사 클래스는 앱 컨테이너의 형제 요소로 스피너를 설정하고 인접한 형제 조합기를 사용하여 컨테이너가 비어 있는 한 표시합니다().+

class App extends React.Component {
  state = {
    loading: true
  };

  componentDidMount() {
    // this simulates an async action, after which the component will render the content
    demoAsyncCall().then(() => this.setState({ loading: false }));
  }
  
  render() {
    const { loading } = this.state;
    
    if(loading) { // if your component doesn't have to wait for async data, remove this block 
      return null; // render null when app is not ready
    }
    
    return (
      <div>I'm the app</div>
    ); 
  }
}

function demoAsyncCall() {
  return new Promise((resolve) => setTimeout(() => resolve(), 2500));
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
#app:not(:empty) + .sk-cube-grid {
  display: none;
}

.sk-cube-grid {
  width: 40px;
  height: 40px;
  margin: 100px auto;
}

.sk-cube-grid .sk-cube {
  width: 33%;
  height: 33%;
  background-color: #333;
  float: left;
  animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
}

.sk-cube-grid .sk-cube1 {
  animation-delay: 0.2s;
}

.sk-cube-grid .sk-cube2 {
  animation-delay: 0.3s;
}

.sk-cube-grid .sk-cube3 {
  animation-delay: 0.4s;
}

.sk-cube-grid .sk-cube4 {
  animation-delay: 0.1s;
}

.sk-cube-grid .sk-cube5 {
  animation-delay: 0.2s;
}

.sk-cube-grid .sk-cube6 {
  animation-delay: 0.3s;
}

.sk-cube-grid .sk-cube7 {
  animation-delay: 0s;
}

.sk-cube-grid .sk-cube8 {
  animation-delay: 0.1s;
}

.sk-cube-grid .sk-cube9 {
  animation-delay: 0.2s;
}

@keyframes sk-cubeGridScaleDelay {
  0%,
  70%,
  100% {
    transform: scale3D(1, 1, 1);
  }
  35% {
    transform: scale3D(0, 0, 1);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>

<div id="app"></div>
<!-- add class loader to container -->

<div class="sk-cube-grid">
  <div class="sk-cube sk-cube1"></div>
  <div class="sk-cube sk-cube2"></div>
  <div class="sk-cube sk-cube3"></div>
  <div class="sk-cube sk-cube4"></div>
  <div class="sk-cube sk-cube5"></div>
  <div class="sk-cube sk-cube6"></div>
  <div class="sk-cube sk-cube7"></div>
  <div class="sk-cube sk-cube8"></div>
  <div class="sk-cube sk-cube9"></div>
</div>


해결책 2 - 스피너 "핸들러"를 소품으로 사용

상태를 하려면 , 의 기능 「기능」을 합니다.showSpinner ★★★★★★★★★★★★★★★★★」hideSpinner이치이 함수는 DOM을 조작하거나 스피너를 제어하는 데 필요한 모든 작업을 수행할 수 있습니다.이와 같이, React는 「외부」를 의식하지 않고, DOM을 직접 제어할 필요도 없습니다.테스트를 위해 또는 로직을 변경해야 하는 경우 쉽게 함수를 교체할 수 있으며, 반응 트리의 다른 구성 요소에 이러한 함수를 전달할 수 있습니다.

예 1

const loader = document.querySelector('.loader');

// if you want to show the loader when React loads data again
const showLoader = () => loader.classList.remove('loader--hide');

const hideLoader = () => loader.classList.add('loader--hide');

class App extends React.Component {
  componentDidMount() {
    this.props.hideLoader();
  }
  
  render() {   
    return (
      <div>I'm the app</div>
    ); 
  }
}

// the setTimeout simulates the time it takes react to load, and is not part of the solution
setTimeout(() => 
  // the show/hide functions are passed as props
  ReactDOM.render(
    <App
      hideLoader={hideLoader}
      showLoader={showLoader} 
      />,
    document.getElementById('app')
  )
, 1000);
.loader {
  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;
  transition: opacity 0.3s;
}

.loader--hide {
  opacity: 0;
}

@keyframes load8 {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>

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

<div class="loader"></div>

예 2 - 훅

이 예에서는 구성 요소가 마운트된 후 후 후크를 사용하여 스피너를 숨깁니다.

const { useEffect } = React;

const loader = document.querySelector('.loader');

// if you want to show the loader when React loads data again
const showLoader = () => loader.classList.remove('loader--hide');

const hideLoader = () => loader.classList.add('loader--hide');

const App = ({ hideLoader }) => {
  useEffect(hideLoader, []);
  
  return (
    <div>I'm the app</div>
  ); 
}

// the setTimeout simulates the time it takes react to load, and is not part of the solution
setTimeout(() => 
  // the show/hide functions are passed as props
  ReactDOM.render(
    <App
      hideLoader={hideLoader}
      showLoader={showLoader} 
      />,
    document.getElementById('app')
  )
, 1000);
.loader {
  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;
  transition: opacity 0.3s;
}

.loader--hide {
  opacity: 0;
}

@keyframes load8 {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

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

<div class="loader"></div>

파일loading html 파일)에.index.html예를 들어 html 파일이 로드된 직후에 아이콘이 표시되도록 합니다.

앱 로드가 완료되면 라이프 사이클 훅에 있는 로딩 아이콘을 간단히 제거할 수 있습니다. 저는 보통 이 작업을 합니다.componentDidMount.

하려면 , 「 」를 참조해 .render하다

constructor() {
    this.state = { isLoading: true }
}

componentDidMount() {
    this.setState({isLoading: false})
}

render() {
    return(
        this.state.isLoading ? *showLoadingScreen* : *yourPage()*
    )
}

「」를 합니다.isLoading는 false입니다.componentDidMount.

은 앞으로 일어날 입니다.ReactDOM.render()루트를 제어하다 <div>은 그. 즉, 앱은 그 시점까지 마운트되지 않습니다.

수 .index.html 내의 <div>리액트가 이어받을 때까지 화면에 표시됩니다.

에게 가장 로더 요소」)를할 수 .svg

라이프 사이클 방법에서는 삭제할 필요가 없습니다.Respect는 루트의 모든 자식을 대체합니다. <div>당신이 그린 것과 함께<App/>【GIF】【GIF】★★★★★★★★★★★★★★★★★★★★★★」

CodeSandbox의 예

여기에 이미지 설명 입력

index.displaces를 표시합니다.

<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.displaces를 표시합니다.

「」를 사용합니다.debuggerReactDOM.render()snowledge.

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);

위의 사용 사례에 대한 드롭인, 제로 구성 및 제로 종속성 라이브러리를 찾는 사용자는 pace.delocency(https://codebyzach.github.io/pace/docs/))를 사용해 보십시오.

이벤트(ajax, readyState, history pushstate, js event loop 등)에 자동으로 후크하여 커스터마이즈 가능한 로더를 표시합니다.

리액트/릴레이 프로젝트(리액트 라우터를 사용한 내비게이션 변경 처리, 릴레이 요청)와 잘 대응(어플라이언트되지 않고 프로젝트에 pace.js를 사용했기 때문에 효과가 좋았다)

리액트 앱의 용량이 클 경우, 페이지가 로드된 후 실행되기까지 시간이 걸립니다.를 들어,, 리액트하다, 리액트하다.#app의 이 div: .html입니다.

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

대신 페이지 로딩과 초기 리액트 앱 렌더링 사이에서 더 보기 좋게 하기 위해 스타일링과 많은 이미지를 넣을 수 있습니다.

<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를 사용하면 페이지가 로드된 직후에 실제 앱이 표시되므로 작업이 덜 복잡해집니다.

이 안에 만 하면 됩니다.<div id="root"></div>꼬리표를 달면 갈 수 있을 거야!

// Example:

<div id="root">
   <div id="pre-loader">
        <p>Loading Website...</p>
        <img src="/images/my-loader.gif" />
   </div>
</div>

''가<App />로딩되면 React는 으로 React 내의 를 무시합니다.<div id="root">그,, 실실실실실!

현재는 React 16.8에서도 후크를 사용할 수 있습니다.

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

const App = () => {
  const [ spinner, setSpinner ] = useState(true);

  // It will be executed before rendering

  useEffect(() => {
    setTimeout(() => setSpinner(false), 1000)
  }, []);

  // [] means like componentDidMount

  return !spinner && <div>Your content</div>;
};

export default App;

나는 최근에 그 문제를 해결해야 했고, 해결책을 생각해 냈는데, 그것은 나에게 아주 잘 먹힌다.에서 @해 보았습니다만,몇지연이 + @Ori Drori 사용법이에 들지 않습니다).setTimeout기능을 합니다).

제가 생각해낸 건 다음과 같습니다.

index.html

. head'-' - '-' - '-' - '-'

<style media="screen" type="text/css">

.loading {
  -webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
  animation: sk-scaleout 1.0s infinite ease-in-out;
  background-color: black;
  border-radius: 100%;
  height: 6em;
  width: 6em;
}

.container {
  align-items: center;
  background-color: white;
  display: flex;
  height: 100vh;
  justify-content: center;
  width: 100vw;
}

@keyframes sk-scaleout {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
  }
  100% {
    -webkit-transform: scale(1.0);
    opacity: 0;
    transform: scale(1.0);
  }
}

</style>

, 이제.body 삭제:

<div id="spinner" class="container">
  <div class="loading"></div>
</div>

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

그리고 아주 간단한 논리가 내면에 나타납니다.app.js일렌렌렌렌렌 ( 。

const spinner = document.getElementById('spinner');

if (spinner && !spinner.hasAttribute('hidden')) {
  spinner.setAttribute('hidden', 'true');
}

어떻게 작동합니까?

첫 번째 컴포넌트(내 앱에서는app.js경우, '마운트'가 올바르게 마운트됩니다.spinner'숨기다'를 붙여서 숨기고 .hidden그 탓이다.

더 - 더 중요한가요? - 더 중요한가요?!spinner.hasAttribute('hidden'), 「」를 추가할 수 됩니다.hidden모든 컴포넌트 마운트에서 스피너에 속성을 부여하기 때문에 실제로 전체 앱이 로드될 때 한 번만 추가됩니다.

답을 찾았을지도 모르기 때문에 답하기엔 너무 늦은 것인지는 모르겠지만, 이 질문은 정말 유용한 질문이기 때문에 미래의 고객을 위해 제 쪽에서 한 가지 질문을 드리겠습니다.:
저는 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로 후됩니다.
연습 삼아 훅으로 시험해 봤는데 꽤 부드럽게 작동했어요!이치노암호는

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를 좋아하지 않는다면 당신은 당신의 API를 페치에 넣을 수 있습니다.

★★★★★★★★★를 사용하고 있는 경우는react-router제가 만든 리액트 라우터 로딩 라이브러리로 쉽게 로딩 화면을 추가할 수 있습니다.

페이지 전환에도 영향이 있지만, 첫 페이지를 프리로드 하려면 다른 페이지도 프리로드하는 것이 당연하다고 생각합니다.

반응 부하

와 의 Suspense이 라이브러리를 사용하면 데이터를 가져오는 동안에도 로드를 계속할 수 있습니다.기본적으로 이 방법은 다음을 사용하는 것과 매우 유사합니다.isLoading컴포넌트 내의 스테이트를 나타냅니다.다만, 다른 페이지가 많이 있는 경우는, 실장이 훨씬 쉬워집니다.

사용.

라우터의 섹션 가져오기 션 터 가져오기Switch ★★★★★★★★★★★★★★★★★」Route부에서react-router-loading대 대신에react-router-dom

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

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

Add 더하다loading환 스위칭 하 전 에 드 든 트 한 원 지 대 에 prop전 switching루 route before be모 to that하로기는 loaded야해 must every전 prop switching

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

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

Add 더하다loadingContext.done() 시에서의 로딩 방법loading 소품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>

React-progress-2 npm 패키지를 사용하고 있습니다.이는 의존성이 전혀 없고 ReactJs에서 매우 잘 작동합니다.

https://github.com/milworm/react-progress-2

설치:

npm install react-progress-2

프로젝트에 react-progress-2/main.css를 포함합니다.

import "node_modules/react-progress-2/main.css";

react-progress-2상위 컴포넌트 어딘가에 배치합니다.하다

import React from "react";
import Progress from "react-progress-2";

var Layout = React.createClass({
render: function() {
    return (
        <div className="layout">
            <Progress.Component/>
                {/* other components go here*/}
            </div>
        );
    }
});

때는 .Progress.show()예를 들어 다음과 같습니다.

loadFeed: function() {
    Progress.show();
    // do your ajax thing.
},

onLoadFeedCallback: function() {
    Progress.hide();
    // render feed.
}

해 주세요, 그 세주주주 please please please please please please please please 。show ★★★★★★★★★★★★★★★★★」hide 있기 .또는 show calls의 hide calls의 hide calls는 의 show calls의 hide calls는 n개의 show calls의 hide calls의 hide calls를 합니다.Progress.hideAll().

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;
    }
  }

앱에서도 리액트를 사용하고 있습니다.Axios 대행 수신기를 사용하는 요청의 경우, 로더 화면(예시를 보여 준 것처럼 전체 페이지)을 만드는 가장 좋은 방법은 예를 들어 내부 대행 수신기에 클래스 또는 ID를 추가하는 것입니다(여기서는 일부 커스텀 코드가 있는 공식 문서의 코드).

// 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);
  }); 

그런 다음 CSS에서 의사 요소를 사용하여 로더를 구현합니다(또는 원하는 대로 본문이 아닌 다른 요소에 클래스 또는 ID 추가). 배경색을 불투명 또는 투명 등으로 설정할 수 있습니다.예:

custom-loader:before {
    background: #000000;
    content: "";
    position: fixed;
    ...
}

custom-loader:after {
    background: #000000;
    content: "Loading content...";
    position: fixed;
    color: white;
    ...
}

이것은 나의 실장입니다.답변은

./public/index.displaces

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

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;

반응에서 느린 로드를 사용하면 쉽게 할 수 있습니다.그러기 위해서는 게으름과 그런 반응에서 오는 서스펜스를 이용해야 한다.

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을 렌더링할 때마다 Loading component가 위의 폴백 속성에 지정된 대로 표시됩니다.ajax 요구는 componentDidMount()에서만 수행해 주세요.

이 문제는 React의 느린 기능으로 쉽게 해결할 수 있습니다.

import { Suspense, lazy } from "react"
import Loading from "components/Loading"

const Dashboard = lazy(() => import("containers/Dashboard"))

const App = () => (
  <Suspense fallback={<Loading />}>
    <Dashboard />
  </Suspense>
)

export default App

Dashboard 구성 요소가 아직 로드 중인 동안 로드 구성 요소가 표시됩니다.

공용 폴더에서 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>

로고가 로드 프로세스 중에 페이지 중앙에 표시됩니다.그리고 몇 초 후에 React에 의해 대체됩니다.

그렇게 많은 노력이 필요하지 않습니다. 여기 기본적인 예가 있습니다.

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

리액트 앱의 시작은 메인 번들 다운로드를 기반으로 합니다.React 앱은 브라우저에서 기본 번들을 다운로드한 후에만 시작됩니다.이는 로딩이 느린 아키텍처의 경우에도 해당됩니다.그러나 사실 우리는 어떤 번들의 이름도 정확하게 말할 수 없습니다.웹 팩은 'npm run build' 명령을 실행할 때 각 번들 끝에 해시 값을 추가합니다.물론 해시 설정을 변경하면 이를 피할 수 있지만 브라우저의 캐시 데이터 문제에 심각한 영향을 미칩니다.브라우저는 번들명이 동일하기 때문에 새로운 버전을 채택하지 않을 수 있습니다.이 상황에 대처하려면 webpack + js + CSS 접근법이 필요합니다.

다음과 같이 public/index.flash를 변경합니다.

<!DOCTYPE html>
<html lang="en" xml:lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=3.0, shrink-to-fit=no">
  <meta name="theme-color" content="#000000">
  <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
  <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
  <style>
 .percentage {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 150px;
      height: 150px;
      border: 1px solid #ccc;
      background-color: #f3f3f3;
      -webkit-transform: translate(-50%, -50%);
          -ms-transform: translate(-50%, -50%);
              transform: translate(-50%, -50%);
      border: 1.1em solid rgba(0, 0, 0, 0.2);
      border-radius: 50%;
      overflow: hidden;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
          -ms-flex-pack: center;
              justify-content: center;
      -webkit-box-align: center;
          -ms-flex-align: center;
              align-items: center;
    }

    .innerpercentage {
      font-size: 20px;
    }
  </style>
  <script>
    function showPercentage(value) {
      document.getElementById('percentage').innerHTML = (value * 100).toFixed() + "%";
    }
    var req = new XMLHttpRequest();
    req.addEventListener("progress", function (event) {
      if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total;
        showPercentage(percentComplete)
        // ...
      } else {
        document.getElementById('percentage').innerHTML = "Loading..";
      }
    }, false);

    // load responseText into a new script element
    req.addEventListener("load", function (event) {
      var e = event.target;
      var s = document.createElement("script");
      s.innerHTML = e.responseText;
      document.documentElement.appendChild(s);
      document.getElementById('parentDiv').style.display = 'none';

    }, false);

    var bundleName = "<%= htmlWebpackPlugin.files.chunks.main.entry %>";
    req.open("GET", bundleName);
    req.send();

  </script>
  <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->

  <title>App Name</title>
  <link href="<%= htmlWebpackPlugin.files.chunks.main.css[0] %>" rel="stylesheet">
</head>

<body>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
  <div id="parentDiv" class="percentage">
    <div id="percentage" class="innerpercentage">loading</div>
  </div>
  <div id="root"></div>
  <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
</body>

</html>

프로덕션 웹 팩 구성에서 HtmlWebpackPlugin 옵션을 다음과 같이 변경합니다.

 new HtmlWebpackPlugin({
          inject: false,
...

컨피규레이션파일을 취득하려면 , 「eject」커맨드를 사용할 필요가 있는 경우가 있습니다.최신 웹 팩에는 프로젝트를 꺼내지 않고 HtmlWebpackPlugin을 구성하는 옵션이 있을 수 있습니다.여기에 이미지 설명 입력

나도 @Ori Drori의 답변을 사용하여 간신히 작동시켰다.React 코드가 커지면 클라이언트 브라우저가 처음 액세스할 때 다운로드해야 하는 컴파일된 번들도 커집니다.이를 제대로 처리하지 않으면 사용자 경험 문제가 발생합니다.

@Ori answer에 추가한 것은 body 태그의 index.html onload Atribut에 onload 함수를 추가하여 실행함으로써 브라우즈에서 모든 것이 완전히 로드된 후 로더가 사라지도록 하기 위한 것입니다.다음 스니펫을 참조해 주십시오.

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

Pace를 사용하면 어떨까요?

여기서 이 링크 주소를 사용합니다.

https://github.hubspot.com/pace/docs/welcome/

1. 웹사이트에서 원하는 스타일을 선택하여 index.css에 붙여넣습니다.

2. cdnjs로 이동합니다.Pace Js 링크를 복사하여 public/index.html 스크립트태그에 추가합니다.

3. 자동으로 웹 로드를 감지하여 브라우저 상단에 속도를 표시합니다.

또한 css에서 높이와 애니메이션을 수정할 수도 있습니다.

가장 중요한 질문은 '로드'라는 것은 무엇을 의미합니까?탑재되는 물리적인 요소에 대해서라면, 여기의 첫 번째 답변 중 몇 가지는 훌륭합니다.그러나 앱이 가장 먼저 인증을 확인하는 경우, 실제로 로드하는 것은 사용자가 권한이 있는 사용자 또는 권한이 없는 사용자로 분류된 쿠키를 전달했는지 여부에 대한 백엔드로부터의 데이터입니다.

이는 환원수를 기반으로 하지만 일반 반응 상태 모형으로 쉽게 변경할 수 있습니다.

작업 작성자:

export const getTodos = () => {
  return async dispatch => {
    let res;
    try {
      res = await axios.get('/todos/get');

      dispatch({
        type: AUTH,
        auth: true
      });
      dispatch({
        type: GET_TODOS,
        todos: res.data.todos
      });
    } catch (e) {
    } finally {
      dispatch({
        type: LOADING,
        loading: false
      });
    }
  };
};

마지막 부분은 사용자가 자동 처리되었는지 여부에 관계없이 응답을 받은 후 로드 화면이 사라짐을 의미합니다.

로드하는 컴포넌트는 다음과 같습니다.

class App extends Component {
  renderLayout() {
    const {
      loading,
      auth,
      username,
      error,
      handleSidebarClick,
      handleCloseModal
    } = this.props;
    if (loading) {
      return <Loading />;
    }
    return (
      ...
    );
  }

  ...

  componentDidMount() {
    this.props.getTodos();
  }

...

  render() {
    return this.renderLayout();
 }

}

state.loading이 truthy일 경우 항상 로딩 화면이 나타납니다.componentDidMount에서는 getTodos 함수를 호출합니다.이 함수는 응답을 받았을 때 state.loading false를 실행하는 액션 크리에이터입니다(오류일 수 있습니다).컴포넌트가 갱신되고 콜이 다시 렌더링되며, 이번에는 if 스테이트먼트로 인해 로딩 화면이 표시되지 않습니다.

React Documentation에서 소스.

React.lazy 함수를 사용하면 동적 가져오기를 일반 구성 요소로 렌더링할 수 있습니다.

그러면 이 구성 요소가 처음 렌더링될 때 OtherComponent가 포함된 번들이 자동으로 로드됩니다.

React.lazy는 동적 Import()를 호출해야 하는 함수를 사용합니다.React 컴포넌트를 포함한 디폴트내보내기 모듈로 해결되는 Promise를 반환해야 합니다.

그런 다음 느린 구성 요소를 Suspendance 구성 요소 안에 렌더링해야 합니다. 그러면 느린 구성 요소가 로드되기를 기다리는 동안 몇 가지 폴백 컨텐츠(로드 표시기 등)를 표시할 수 있습니다.

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

예비 소품은 구성요소가 로드되기를 기다리는 동안 렌더링하려는 모든 React 요소를 수락합니다.Suspend 구성 요소는 느린 구성 요소 위에 배치할 수 있습니다.단일 Suspend 구성 요소로 여러 개의 느린 구성 요소를 래핑할 수도 있습니다.

원천

언급URL : https://stackoverflow.com/questions/40987309/react-display-loading-screen-while-dom-is-rendering

반응형