[reactjs] 반응-DOM이 렌더링되는 동안 로딩 화면이 표시됩니까?

Google Adsense 애플리케이션 페이지의 예입니다. 메인 페이지 이전에 표시된 로딩 화면이 나타납니다.

여기에 이미지 설명을 입력하십시오

React와 동일한 작업을 수행하는 방법을 모르겠습니다 .React 구성 요소로 렌더링 된 로딩 화면을 만들면 DOM이 렌더링 될 때까지 기다려야하기 때문에 페이지가로드되는 동안 표시되지 않기 때문입니다.

업데이트 :

스크린 로더를 넣고 index.htmlReact componentDidMount()수명주기 방법으로 제거하여 접근 방식의 예를 만들었습니다 .

반응 로딩 화면 .



답변

로드 아이콘을 html 파일 (예 : index.html)에 배치하면 html 파일이로드 된 후 바로 아이콘을 볼 수 있습니다.

앱이 로딩을 마치면 라이프 사이클 후크에서 로딩 아이콘을 제거 할 수 componentDidMount있습니다.


답변

목표

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

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

해결 방법 1-: 비상 의사 클래스

반응을 DOM 컨테이너에 렌더링하기 때문에 <div id="app"></div>해당 컨테이너에 스피너를 추가 할 수 있으며 반응이로드되어 렌더링되면 스피너가 사라집니다.

React ReactDOM.render()가 호출 되는 즉시 컨테이너의 내용을 대체하므로 반응 루트 내에 DOM 요소 (예 : div)를 추가 할 수 없습니다 . 렌더링하더라도 null내용은 여전히 ​​주석으로 대체됩니다 <!-- react-empty: 1 -->. 즉, 주요 구성 요소가 마운트되는 동안 로더를 표시하려는 경우 데이터가로드되지만 실제로 아무것도 렌더링 <div id="app"><div class="loader"></div></div>되지 않으면 컨테이너 ( 예 🙂 내부에 배치 된 로더 마크 업 이 작동하지 않습니다.

해결 방법은 스피너 클래스를 반응 컨테이너에 추가하고 :empty의사 클래스를 사용하는 것 입니다. 컨테이너에 아무것도 렌더링되지 않는 한 스피너가 표시됩니다 (코멘트는 포함되지 않음). 반응이 주석 이외의 것을 렌더링하자마자 로더가 사라집니다.

실시 예 1

이 예에서는 null준비 될 때까지 렌더링되는 구성 요소를 볼 수 있습니다 . 컨테이너도 로더입니다- <div id="app" class="app"></div>그리고 로더의 클래스는 그것이 작동하는 경우에만 작동합니다 :empty(코드 주석 참조).

실시 예 2

:empty의사 클래스를 사용하여 선택기를 표시하거나 숨기는 변형 은 스피너를 앱 컨테이너의 형제 요소로 설정하고 인접한 형제 조합기 ( +)를 사용하여 컨테이너가 비어있는 동안 표시하는 것입니다 .


해결 방법 2- 스피너 “핸들러”를 소품으로 전달

, 스피 표시 상태를 통해보다 세밀하게 제어 할 수 있습니다 두 가지 기능을 만들려면 showSpinner하고 hideSpinner, 소품을 통해 루트 컨테이너로 전달합니다. 함수는 DOM을 조작하거나 스피너를 제어하는 ​​데 필요한 모든 작업을 수행 할 수 있습니다. 이런 식으로 React는 “외부 세계”를 인식하지 못하고 DOM을 직접 제어 할 필요가 없습니다. 테스트 할 기능을 쉽게 교체하거나 로직을 변경해야하는 경우 React 트리의 다른 구성 요소로 전달할 수 있습니다.

실시 예 1

예 2-후크

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


답변

이에 대한 해결 방법은 다음과 같습니다.

렌더링 함수에서 다음과 같이하십시오.

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

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

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

생성자에서 isLoading을 true로, componentDidMount에서 false를 초기화합니다.


답변

위의 유스 케이스에 대해 드롭 인, 제로 구성 및 제로 종속성 라이브러리를 찾는 사람이 있다면 pace.js ( http://github.hubspot.com/pace/docs/welcome/ )를 사용해보십시오 .

이벤트 (ajax, readyState, history pushstate, js event loop 등)에 자동으로 연결되어 사용자 정의 가능한 로더를 보여줍니다.

리 액트 / 릴레이 프로젝트 (리 액트 라우터, 릴레이 요청을 사용하여 탐색 변경 처리)
와 잘 작동했습니다.


답변

React 앱이 방대한 경우 페이지가로드 된 후 앱이 시작되고 실행되는 데 실제로 시간이 걸립니다. 앱의 React 부분을에 마운트한다고 가정 해보십시오 #app. 일반적으로 index.html의이 요소는 단순히 빈 div입니다.

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

대신 페이지로드와 DOM에 대한 초기 React 앱 렌더링 사이에서 더 잘 보이도록 몇 가지 스타일과 이미지를 배치하십시오.

<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을 사용하면 페이지가로드 된 후 사용자가 실제 앱을 실제로 볼 수 있기 때문에 작업이 덜 복잡해집니다.


답변

이것은 루트를ReactDOM.render() 제어 하기 전에 발생 합니다 <div> . 즉, 앱이 해당 시점까지 마운트되지 않았습니다.

따라서 index.html루트 안의 파일에 로더를 추가 할 수 있습니다 <div>. 그리고 React가 인수 할 때까지 화면에 표시됩니다.

가장 적합한 로더 요소 svg를 애니메이션으로 사용할 수 있습니다 .

수명주기 방법에서 제거 할 필요는 없습니다. 아래 GIF에서 볼 수 있듯이 React는 루트 의 모든 하위 요소를 <div>렌더링 된로 대체합니다 <App/>.

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

실행 debugger하기 전에 페이지를 검사하는 데 사용 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);


답변

요즘에는 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;