React - отображать экран загрузки во время рендеринга DOM?


160

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

введите описание изображения здесь

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

Обновлено :

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

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


Покажите, что вы хотите показать, в простом js, затем сделайте это скрытым или удалите из DOM, когда response смонтирован. Все, что вам нужно сделать, это скрыть это от кода реакции.
FurkanO 06

Это просто замечательно! Спасибо.
Арман Карими

Ответы:


110

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

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


16
Если вы подключите корневой компонент к родительскому узлу этого значка, нет необходимости даже удалять его вручную. React очистит дочерние элементы узла монтирования и вместо этого поместит туда свой новый отрендеренный DOM.
Ришат 06

6
Я не помещаю значок в корневой узел приложения React, мне он просто не подходит
kkkkkkk 06

1
есть ли обратная сторона этого для PWA? будет ли это мешать работе заставки по умолчанию?
Benmneb

189

Цель

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

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

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

Поскольку вы визуализируете реакцию в контейнер DOM - <div id="app"></div>, вы можете добавить счетчик в этот контейнер, и когда реакция загрузится и отобразится, счетчик исчезнет.

Вы не можете добавить элемент DOM (например, div) в корень реакции, поскольку React заменит содержимое контейнера, как только он ReactDOM.render()будет вызван. Даже если вы nullвыполните рендеринг , контент все равно будет заменен комментарием - <!-- react-empty: 1 -->. Это означает, что если вы хотите отобразить загрузчик во время монтирования основного компонента, данные загружаются, но на самом деле ничего не отображается, разметка загрузчика, размещенная внутри контейнера ( <div id="app"><div class="loader"></div></div>например), не будет работать.

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

Пример 1

В этом примере вы можете увидеть компонент, который рендерится, nullпока не будет готов. Контейнер также является загрузчиком <div id="app" class="app"></div>, а класс загрузчика будет работать, только если он :empty(см. Комментарии в коде):

Пример 2

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


Решение 2. Передайте «обработчики» счетчиков в качестве реквизита.

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

Пример 1

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

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


Не могли бы вы уточнить, где должны быть последние 2 раздела кода? Первый явно находится в файле src javascript для компонента реакции, третий, как я предполагаю, входит в шаблон html, который должен отображаться указанным файлом js, но куда идет второй?
levraininjaneer 03

1
Второй - CSS. Я использовал глобальный CSS, но вы можете использовать CSS-модули или CSS в JS. Третий - это HTML-файл, который при необходимости может включать разметку счетчика (2-й пример).
Ори Дрори

4
@dryleaf - setTimeout не является частью решения. Он имитирует ожидание асинхронного действия перед рендерингом содержимого.
Ори Дрори

1
@ hamza-jutt - вам следует задать новый вопрос по этому поводу.
Ори Дрори

1
return nullдобавляет комментарий, который будет отображаться как пустой экран. Псевдокласс: empty работает вместе с ним, return nullпоскольку он игнорирует комментарии при определении, пуст ли контейнер.
Сударшан

44

Обходной путь для этого:

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

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

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

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

Инициализируйте isLoading как true в конструкторе и false в componentDidMount


Когда мы вызвали метод ajax для загрузки данных в дочерние компоненты. componentDidMount вызывается перед заполнением данных дочернего компонента. Как мы преодолеваем такую ​​проблему?
dush88c

3
Для Mounting Life cyle это нормально, хотите что-нибудь добавить для жизненного цикла обновления?
Закир

я должен делать это на всех страницах или только в записи приложения
Мадуэкве Педро

17

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

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

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


Привет! Подскажите, как его использовать с React?
uneet7

просто прикрепите сценарий public/index.htmlи выберите стиль. это мертвенно простой, потрясающий плагин. Спасибо.
PJ3

Без этого ответа я бы не нашел темпа. Его было так просто включить, и с небольшой магией CSS и некоторыми вложениями событий я смог заблокировать / отключить приложение во время переходов и настроить счетчик.
invertedSpear

15

Это произойдет до ReactDOM.render()того, как рут получит контроль <div>. Т.е. ваше приложение не будет установлено до этого момента.

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

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

Вам не нужно удалять его ни в одном методе жизненного цикла. React заменит любых дочерних элементов своего корня <div> на ваши отрисованные <App/>, как мы видим на GIF-изображении ниже.

Пример на 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);

красивое и элегантное решение
Гал Маргалит

1
Рад, что помог!
cbdeveloper

13

Когда ваше приложение 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, все будет проще, потому что пользователь фактически увидит реальное приложение сразу после загрузки страницы.


Это работает также у меня есть два места, где происходит загрузка. Одно из них - массивное приложение. и далее идет подготовка (установка различных компонентов). Итак, я получаю этап мигания, потому что app.render берет на себя, и анимация сбрасывается ( действительно заменяется ). Есть ли способ избежать этой вспышки? Будет ли React сравнивать DOM один в один? Но
Алексис

8

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

Вы упускаете суть, нет реакции, пока не загрузится bundle.js. Html загружается перед любыми скриптами, поэтому должна отображаться страница загрузки.
Кристиан Э.

5

Недавно мне пришлось столкнуться с этой проблемой, и я нашел решение, которое мне подходит. Однако я пробовал решение @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атрибут в счетчик при каждом монтировании компонента, поэтому на самом деле он будет добавлен только один раз, когда загружается все приложение.


5

Установка тайм-аута в 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;
    }
  }

4

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

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

Установка:

npm install react-progress-2

Включите в свой проект response-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.
}

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


4

Я также использую 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;
    ...
}

3

Измените расположение файла 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.


3

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

<!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сделать так, чтобы он выглядел как ваш пример.


2

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

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

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

1

Самый важный вопрос: что вы подразумеваете под «загрузкой»? Если вы говорите о монтируемом физическом элементе, некоторые из первых ответов здесь отличные. Однако, если первое, что делает ваше приложение, - это проверка аутентификации, на самом деле вы загружаете данные из бэкэнда, передал ли пользователь файл 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 <Loading />;
    }
    return (
      ...
    );
  }

  ...

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

...

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

}

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


1

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

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

<!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 без извлечения проекта. введите описание изображения здесь


1

А как насчет использования темпа

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

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

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

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

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

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


Великолепно, интегрируется в кратчайшие сроки.
UzumakiL

1

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

./public/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;

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.