Это пример со страницы приложения Google AdSense. Экран загрузки, отображаемый до главной страницы, отображается после.

enter image description here

• 100001

Обновлено:

Я сделал пример своего подхода, поместив загрузчик экрана в index.html и удалив его в React componentDidMount () метод жизненного цикла.

Пример и экран загрузки-реакции.

Ответы (23)

Это можно сделать, поместив значок загрузки в ваш html-файл (например, index.html), чтобы пользователи видели значок сразу после загрузки html-файла.

Когда ваше приложение завершает загрузку, вы можете просто удалить этот значок загрузки в ловушке жизненного цикла, я обычно делаю это в componentDidMount.

Это произойдет до того, как ReactDOM.render () возьмет на себя управление root

. Т.е. ваше приложение не будет установлено до этого момента.

Таким образом, вы можете добавить свой загрузчик в файл index.html внутри корня

. И это будет видно на экране, пока React не возьмет верх.

Вы можете использовать любой элемент загрузчика, который вам больше подходит (svg с анимацией, например).

Вам не нужно удалять его ни в одном методе жизненного цикла. React заменит всех дочерних элементов своего root

вашим отрисованным , как мы можем видеть в GIF ниже.

Пример на CodeSandbox

enter image description here

index.html


  



  

index.js

Использование отладчика для проверки страницы перед запуском ReactDOM.render ().

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

function App() {
  return (
    

Hello CodeSandbox

Start editing to see some magic happen!

); } debugger; // TO INSPECT THE PAGE BEFORE 1ST RENDER const rootElement = document.getElementById("root"); ReactDOM.render(, rootElement);

Цель

После рендеринга html-страницы немедленно отобразить счетчик (пока React загружается) и скрыть его после того, как React будет готов.

Поскольку счетчик отображается в чистом HTML / CSS (за пределами домена React), React не должен напрямую управлять процессом отображения / скрытия, а реализация должна быть прозрачной для React.

Решение 1 - псевдокласс пустой

Поскольку вы визуализируете реакцию в контейнер DOM -

, вы можете добавить счетчик в этот контейнер, и когда реакция загрузится и отобразит, счетчик исчезнет.

Вы не можете добавить элемент DOM (например, div) внутри корня реакции, поскольку React заменит содержимое контейнера, как только будет вызвано ReactDOM.render (). Даже если вы отобразите null, содержимое все равно будет заменено комментарием - . Это означает, что если вы хотите отобразить загрузчик во время монтирования основного компонента, данные загружаются, но на самом деле ничего не отображается, разметка загрузчика помещается внутри контейнера (

например) не будет работать.

Обходной путь - добавить класс счетчика в контейнер реакции и использовать псевдокласс : empty. Счетчик будет виден, пока ничего не отображается в контейнере (комментарии не учитываются). Как только response отобразит что-то, кроме комментария, загрузчик исчезнет.

Пример 1

В этом примере вы можете увидеть компонент, который отображает null, пока он не будет готов. Контейнер также является загрузчиком -

, а класс загрузчика будет работать, только если он : пустой ( см. комментарии в коде):

класс App расширяет React.Component {
  state = {
    загрузка: правда
  };

  componentDidMount () {
    // это имитирует асинхронное действие, после которого компонент будет отображать контент
    demoAsyncCall (). then (() => this.setState ({загрузка: false}));
  }
  
  оказывать() {
    const {загрузка} = this.state;
    
    if (loading) {// если вашему компоненту не нужно ждать асинхронного действия, удалите этот блок
      return null; // рендерим null, когда приложение не готово
    }
    
    возвращение (
      
Я приложение
); } } function demoAsyncCall () { вернуть новое обещание ((решить) => setTimeout (() => решить (), 2500)); } ReactDOM.render ( <Приложение />, document.getElementById ('приложение') );
.loader: empty {
  позиция: абсолютная;
  вверху: calc (50% - 4em);
  слева: calc (50% - 4em);
  ширина: 6em;
  высота: 6em;
  граница: 1.1em solid rgba (0, 0, 0, 0.2);
  граница слева: 1.1em solid # 000000;
  радиус границы: 50%;
  анимация: load8 1.1s бесконечная линейная;
}

@keyframes load8 {
  0% {
    преобразовать: повернуть (0deg);
  }
  100% {
    преобразовать: повернуть (360 градусов);
  }
}



Пример 2

Вариант использования псевдокласса : empty для отображения / скрытия селектора, устанавливает счетчик как родственный элемент для контейнера приложения и показывает его, пока контейнер пуст, с помощьюкомбинатор соседних братьев (+):

класс App расширяет React.Component {
  state = {
    загрузка: правда
  };

  componentDidMount () {
    // это имитирует асинхронное действие, после которого компонент будет отображать контент
    demoAsyncCall (). then (() => this.setState ({загрузка: false}));
  }
  
  оказывать() {
    const {загрузка} = this.state;
    
    if (loading) {// если вашему компоненту не нужно ждать асинхронных данных, удалите этот блок
      return null; // рендерим null, когда приложение не готово
    }
    
    возвращение (
      
Я приложение
); } } function demoAsyncCall () { вернуть новое обещание ((решить) => setTimeout (() => решить (), 2500)); } ReactDOM.render ( <Приложение />, document.getElementById ('приложение') );
# app: not (: empty) + .sk-cube-grid {
  дисплей: нет;
}

.sk-cube-grid {
  ширина: 40 пикселей;
  высота: 40 пикселей;
  маржа: 100 пикселей автоматически;
}

.sk-cube-grid .sk-cube {
  ширина: 33%;
  высота: 33%;
  цвет фона: # 333;
  плыть налево;
  анимация: sk-cubeGridScaleDelay 1.3s бесконечная простота вставки;
}

.sk-cube-grid .sk-cube1 {
  задержка анимации: 0,2 с;
}

.sk-cube-grid .sk-cube2 {
  задержка анимации: 0,3 с;
}

.sk-cube-grid .sk-cube3 {
  анимация-задержка: 0,4 с;
}

.sk-cube-grid .sk-cube4 {
  задержка анимации: 0,1 с;
}

.sk-cube-grid .sk-cube5 {
  задержка анимации: 0,2 с;
}

.sk-cube-grid .sk-cube6 {
  задержка анимации: 0,3 с;
}

.sk-cube-grid .sk-cube7 {
  задержка анимации: 0 с;
}

.sk-cube-grid .sk-cube8 {
  задержка анимации: 0,1 с;
}

.sk-cube-grid .sk-cube9 {
  задержка анимации: 0,2 с;
}

@keyframes sk-cubeGridScaleDelay {
  0%,
  70%,
  100% {
    преобразовать: scale3D (1, 1, 1);
  }
  35% {
    преобразовать: scale3D (0, 0, 1);
  }
}




Решение 2 - Передать "обработчики" счетчика как реквизиты

Чтобы иметь более точный контроль над состоянием отображения счетчиков, создайте две функции showSpinner и hideSpinnerи передайте их корневому контейнеру через props. Функции могут управлять DOM или делать все необходимое для управления счетчиком. Таким образом, React не знает о «внешнем мире» и ему не нужно напрямую контролировать DOM. Вы можете легко заменить функции для тестирования или, если вам нужно изменить логику, и передать их другим компонентам в дереве React.

Пример 1

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

// если вы хотите показать загрузчик, когда React снова загрузит данные
const showLoader = () => loader.classList.remove ('загрузчик - скрыть');

const hideLoader = () => loader.classList.add ('загрузчик - скрыть');

class App extends React.Component {
  componentDidMount () {
    this.props.hideLoader ();
  }
  
  оказывать() {
    возвращение (
      
Я приложение
); } } // setTimeout моделирует время реакции на загрузку и не является частью решения setTimeout (() => // функции отображения / скрытия передаются как реквизиты ReactDOM.render ( <Приложение hideLoader = {hideLoader} showLoader = {showLoader} />, document.getElementById ('приложение') ) , 1000);
.loader {
  позиция: абсолютная;
  вверху: calc (50% - 4em);
  слева: calc (50% - 4em);
  ширина: 6em;
  высота: 6em;
  граница: 1.1em solid rgba (0, 0, 0, 0.2);
  граница слева: 1.1em solid # 000000;
  радиус границы: 50%;
  анимация: load8 1.1s бесконечная линейная;
  переход: непрозрачность 0,3 с;
}

.loader - hide {
  непрозрачность: 0;
}

@keyframes load8 {
  0% {
    преобразовать: повернуть (0deg);
  }
  100% {
    преобразовать: повернуть (360 градусов);
  }
}



Пример 2 - крючки

В этом примере используется хук useEffect, чтобы скрыть счетчик после монтирования компонента.

const {useEffect} = React;

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

// если вы хотите показать загрузчик, когда React снова загрузит данные
const showLoader = () => loader.classList.remove ('загрузчик - скрыть');

const hideLoader = () => loader.classList.add ('загрузчик - скрыть');

const App = ({hideLoader}) => {
  useEffect (hideLoader, []);
  
  возвращение (
    
Я приложение
); } // setTimeout моделирует время реакции на загрузку и не является частью решения setTimeout (() => // функции отображения / скрытия передаются как реквизиты ReactDOM.render ( <Приложение hideLoader = {hideLoader} showLoader = {showLoader} />, document.getElementById ('приложение') ) , 1000);
.loader {
  позиция: абсолютная;
  вверху: calc (50% - 4em);
  слева: calc (50% - 4em);
  ширина: 6em;
  высота: 6em;
  граница: 1.1em solid rgba (0, 0, 0, 0.2);
  граница слева: 1.1em solid # 000000;
  радиус границы: 50%;
  анимация: load8 1.1s бесконечная линейная;
  переход: непрозрачность 0,3 с;
}

.loader - hide {
  непрозрачность: 0;
}

@keyframes load8 {
  0% {
    преобразовать: повернуть (0deg);
  }
  100% {
    преобразовать: повернуть (360 градусов);
  }
}



Измените расположение файла index.html в папке public. Скопируйте изображение в то же место, что и index.html в общей папке. Затем замените часть содержимого index.html, содержащую теги

, на приведенный ниже html-код.

Spideren

Логотип теперь будет отображаться посередине страницы во время загрузки. И через несколько секунд будет заменен на React.

Я использую response-progress-2 npm пакет, который не зависит от нуля и отлично работает в ReactJS.

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

Установка:

npm install react-progress-2

Включите в свой проект response-progress-2 / main.css.

импорт «node_modules / response-progress-2 / main.css»;

Включите response-progress-2 и поместите его где-нибудь в верхнем компоненте, например:

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

var Layout = React.createClass({
render: function() {
    return (
        
{/* other components go here*/}
); } });

Теперь, когда вам нужно показать индикатор, просто вызывайте Progress.show (), например:

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

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

Обратите внимание, что вызовы show и hide складываются, поэтому после n последовательных вызовов show вам нужно сделать n вызовов hide, чтобы скрыть индикатор, или вы можете использовать Progress.hideAll ().

Вам не нужно так много усилий, вот простой пример.





  
  
  
  
  
  
  
   Заголовок 
  <стиль>
    тело {
      маржа: 0;
    }

    .loader-container {
      ширина: 100вв;
      высота: 100вх;
      дисплей: гибкий;
      переполнение: скрыто;
    }

    .loader {
      маржа: авто;
      граница: 5 пикселей с точками #dadada;
      граница-верх: 5px solid # 3498db;
      радиус границы: 50%;
      ширина: 100 пикселей;
      высота: 100 пикселей;
      -webkit-animation: вращать 2с линейно бесконечно;
      анимация: вращение 2с линейно бесконечное;
    }

    @ -webkit-keyframes spin {
      0% {
        -webkit-transform: повернуть (0deg);
      }

      100% {
        -webkit-transform: повернуть (360 градусов);
      }
    }

    @keyframes spin {
      0% {
        преобразовать: повернуть (0deg);
      }

      100% {
        преобразовать: повернуть (360 градусов);
      }
    }

  



  
  

Вы можете поэкспериментировать с HTML и CSS, чтобы он выглядел как ваш пример.

Как насчет использования Pace

Используйте этот адрес ссылки здесь.

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

1. На их веб-сайте выберите нужный стиль и вставьте в index.css

2. перейти на cdnjs Скопируйте ссылку для Pace Js и добавьте в свои теги скрипта в public / index.html

3. Он автоматически определяет веб-загрузки и отображает темп в верхней части браузера.

Вы также можете изменить высоту и анимацию в CSS.

Запуск приложения React основан на загрузке основного пакета. Приложение React запускается только после загрузки основного пакета в браузере. Это верно даже в случае архитектуры отложенной загрузки. Но дело в том, что мы не можем точно указать название каких-либо пакетов. Потому что webpack будет добавлять хеш-значение в конец каждого пакета во время выполнения команды npm run build. Конечно, мы можем избежать этого, изменив настройки хеширования, но это серьезно повлияет на проблему данных кеша в браузере. Браузеры могут не использовать новую версию из-за того же имени пакета. . нам нужен подход webpack + js + CSS, чтобы справиться с этой ситуацией.

измените public / index.html, как показано ниже





  
  
  
  
  
  
  <стиль>
 .percentage {
      позиция: абсолютная;
      верх: 50%;
      осталось: 50%;
      ширина: 150 пикселей;
      высота: 150 пикселей;
      граница: 1px solid #ccc;
      цвет фона: # f3f3f3;
      -webkit-transform: перевести (-50%, -50%);
          -ms-transform: translate (-50%, -50%);
              преобразовать: перевести (-50%, -50%);
      граница: 1.1em solid rgba (0, 0, 0, 0.2);
      радиус границы: 50%;
      переполнение: скрыто;
      дисплей: -webkit-box;
      дисплей: -ms-flexbox;
      дисплей: гибкий;
      -webkit-box-pack: по центру;
          -ms-flex-pack: по центру;
              justify-content: center;
      -webkit-box-align: center;
          -ms-flex-align: center;
              align-items: center;
    }

    .innerpercentage {
      размер шрифта: 20 пикселей;
    }
  
  <сценарий>
    function showPercentage (value) {
      document.getElementById ('процент'). innerHTML = (значение * 100) .toFixed () + «%»;
    }
    var req = новый XMLHttpRequest ();
    req.addEventListener ("прогресс", функция (событие) {
      if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total;
        showPercentage (percentComplete)
        // ...
      } еще {
        document.getElementById ('процент'). innerHTML = "Загрузка ..";
      }
    }, ложный);

    // загружаем responseText в новый элемент скрипта
    req.addEventListener ("загрузка", функция (событие) {
      var e = event.target;
      var s = document.createElement («скрипт»);
      s.innerHTML = e.responseText;
      document.documentElement.appendChild (s);
      document.getElementById ('parentDiv'). style.display = 'none';

    }, ложный);

    var bundleName = "<% = htmlWebpackPlugin.files.chunks.main.entry%>";
    req.open ("ПОЛУЧИТЬ", bundleName);
    req.send ();

  
  

   Название приложения 
  



  
  
загрузка
. Чтобы начать разработку, запустите `npm start` или` yarn start`. Чтобы создать производственный пакет, используйте npm run build или yarn build. ->

В производственной конфигурации веб-пакета измените параметр HtmlWebpackPlugin на ниже

 new HtmlWebpackPlugin({
          inject: false,
...

Возможно, вам потребуется использовать команду «eject», чтобы получить файл конфигурации. последний веб-пакет может иметь возможность настроить HtmlWebpackPlugin без извлечения проекта. enter image description here

Вы можете легко сделать это, используя ленивую загрузку в react. Для этого вам нужно использовать ленивость и ожидание от такой реакции.

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

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

  return props => (
    
      
    
  );
};

export default loadable;

После этого экспортируйте ваши компоненты вот так.

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

И тогда в вашем файле маршрутов используйте это так.

 

Вот и все, теперь вы можете продолжать каждый раз, когда ваша DOM визуализирует, ваш компонент Loading будет отображаться, как мы указали в свойстве fallback выше. Просто убедитесь, что вы выполняете любой запрос ajax только в componentDidMount ()

Если вы используете response-router для управления маршрутами вашего приложения, вы можете легко добавить экран загрузки с библиотекой response-router-loading, которую я сделал.

Это также влияет на переключение страниц, но я думаю, что если вы хотите предварительно загрузить первую страницу, естественно предварительно загрузить и другие страницы.

react-router-loading

Разница между этим методом и Suspense в том, что с помощью этой библиотеки вы можете продолжать загрузку, пока вы получаете данные и так далее. По сути, этот метод очень похож на использование состояния isLoading внутри компонента, но его гораздо проще реализовать, если у вас много разных страниц.

Использование

В разделе вашего роутера import Switch и Route from response-router-loading вместо response-router-dom

импорт {Switch, Route} из "response-router-loading";

<Переключатель>
    
    
    ...

Добавить loading prop к каждому маршруту, который должен быть загружен перед переключением

<переключатель>
    // данные будут загружены перед переключением
    

    // мгновенное переключение, как и раньше
    
    ...

Добавьте loadingContext.done () в конце вашего метода начальной загрузки в компонентах, упомянутых в маршрутах с loading prop (в данном случае это Page1)

импорт {LoadingContext} из "response-router-loading";
const loadingContext = useContext (LoadingContext);

const loading = async () => {
    // загружаем некоторые данные

    // вызываем метод, чтобы указать, что загрузка завершена и мы готовы к переключению
    loadingContext.done ();
};

Вы можете указать экран загрузки, который будет отображаться при первой загрузке вашего приложения

const MyLoadingScreen = () => 
Загрузка ...
...

Если кто-то ищет библиотеку drop-in, zero-config и zero-dependencies для вышеуказанного варианта использования, попробуйте pace.js (https://codebyzach.github.io/pace/docs/).

Он автоматически подключается к событиям (ajax, readyState, history pushstate, js event loop и т. Д.) И показывает настраиваемый загрузчик.

Хорошо работал с нашими проектами реакции / ретрансляции (обрабатывает изменения навигации с помощью response-router, запросы ретрансляции) (Не связан; в наших проектах использовал pace.js, и он отлично работал)

В настоящее время мы можем использовать хуки и в 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 && 
Your content
; }; 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;
    }
  }

Я также использую React в своем приложении. Для запросов я использую перехватчики axios, поэтому отличный способ сделать экран загрузчика (полноэкранный, как вы показали в примере) - это добавить класс или идентификатор, например, к телу внутри перехватчиков (здесь код из официальной документации с некоторым настраиваемым кодом):

// 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 свой загрузчик с псевдоэлементами (или добавьте класс или идентификатор к другому элементу, а не к телу, как вам нравится) - вы можете установить цвет фона на непрозрачный или прозрачный и т. Д. Пример:

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

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

Я также использовал ответ @Ori Drori, и мне удалось заставить его работать. По мере роста вашего кода React будут скомпилированы пакеты, которые клиентский браузер должен будет загрузить при первом доступе. Это создает проблемы с пользовательским интерфейсом, если вы не справляетесь с этим должным образом.

Я добавил в ответ @Ori добавить и выполнить функцию onload в атрибуте index.html on onload тега body, чтобы загрузчик исчезал после того, как все было полностью загружено в браузере, см. Фрагмент ниже :


  
     
     
   
   
     more html here.....
   

Просто добавьте содержимое внутри тега
, и все будет в порядке!

// Example:

Loading Website...

После загрузки React автоматически проигнорирует весь контент внутри тега

, заменив его вашим фактическим приложением!

Решение для этого:

В вашей функции рендеринга сделайте что-то вроде этого:

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

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

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

Инициализировать isLoading как true в конструкторе и false на 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 (
            

{text}

) } } 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 ?  : 

{response.name}

return(
{content}
) } export default App;

Итак, та же логика с хуками. И я получаю красивый счетчик, пока данные загружаются, а затем мои данные!

Да, и, кстати, вы можете поместить свой собственный API в выборку, если вам не нравится этот XD.

Самый главный вопрос: что вы подразумеваете под «загрузкой»? Если вы говорите о монтируемом физическом элементе, некоторые из первых ответов здесь отличные. Однако, если ваше приложение в первую очередь проверяет аутентификацию, то на самом деле вы загружаете данные из бэкэнда, передал ли пользователь файл cookie, который помечает его как авторизованного или неавторизованного пользователя.

Это основано на redux, но вы можете легко изменить его на модель простого состояния реакции.

создатель действия:

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

Часть finally означает, авторизован пользователь или нет, экран загрузки исчезает после получения ответа.

Вот как может выглядеть загружаемый компонент:

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

  ...

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

...

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

}

Если state.loading правдиво, мы всегда будем видеть экран загрузки. В componentDidMount мы вызываем нашу функцию getTodos, которая является создателем действия, который превращает state.loading в ложный, когда мы получаем ответ (который может быть ошибкой). Наш компонент обновляется, снова вызывает рендеринг, и на этот раз нет экрана загрузки из-за оператора if.

This problem can be easily solved with the lazy feature of React.

импорт {Suspense, lazy} из "react"
Импорт Загрузка из "Компоненты / Загрузка"

const Dashboard = lazy (() => import ("контейнеры / информационная панель"))

const App = () => (
  <Отложенный откат = {}>
    <Панель управления />
  
)

экспортировать приложение по умолчанию

Компонент загрузки будет отображаться, пока еще загружается компонент Dashboard.

это моя реализация, основанная на ответах

./public/index.html





  React App
  



  

. / 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 (
    

App react

); }; export default App;

Недавно мне пришлось столкнуться с этой проблемой, и я нашел решение, которое мне подходит. Однако я пробовал решение @Ori Drori, описанное выше, и, к сожалению, оно не сработало (были некоторые задержки + мне не нравится использование там функции setTimeout).

Вот что я придумал:

index.html файл

Внутри заголовок тег - стили для индикатора:


Теперь тег body:

И затем приходит очень простая логика внутри файла app.js (в функции рендеринга):

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

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

Как работает?

Когда первый компонент (в моем приложении это app.js также в большинстве случаев) монтируется правильно, счетчик скрывается с применением атрибута hidden к нему.

Что важнее добавить - Условие! Spinner.hasAttribute ('hidden') предотвращает добавление атрибута hidden к счетчику при каждом монтировании компонента, поэтому на самом деле он будет добавлен только один раз при загрузке всего приложения.

Когда ваше приложение React огромно, ему действительно нужно время, чтобы оно заработало после загрузки страницы. Скажем, вы монтируете свою React-часть приложения в # app. Обычно этот элемент в вашем index.html - это просто пустой div:

Вместо этого вы можете добавить немного стилей и кучу изображений, чтобы они лучше смотрелись между загрузкой страницы и начальным рендерингом приложения React в DOM:

Hold on, it's loading!

После загрузки страницы пользователь сразу увидит исходное содержимое index.html. Вскоре после этого, когда React будет готов смонтировать всю иерархию визуализированных компонентов к этому узлу DOM, пользователь увидит реальное приложение.

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


Если вы используете SSR, все будет менее сложно, потому что пользователь фактически увидит реальное приложение сразу после загрузки страницы.

2022 WebDevInsider