Backdrop с индикатором загрузки

Backdrop — это компонент из библиотеки MUI (Material-UI), который позволяет создавать затемнённый слой поверх основного контента. Обычно он применяется для отображения состояния загрузки или блокировки интерфейса при выполнении асинхронных операций. Backdrop часто сочетается с CircularProgress, создавая наглядный индикатор загрузки.


Подключение компонентов

Для использования Backdrop и индикатора загрузки необходимо импортировать соответствующие элементы из MUI:

import React, { useState } from 'react';
import Backdrop from '@mui/material/Backdrop';
import CircularProgress from '@mui/material/CircularProgress';
import Button from '@mui/material/Button';

Ключевые моменты:

  • Backdrop отвечает за затемнённый фон.
  • CircularProgress создаёт анимированный индикатор загрузки.
  • Компоненты MUI полностью поддерживают стилизацию через sx и styled.

Базовый пример использования

Создание простого Backdrop с индикатором загрузки:

function LoadingBackdrop() {
  const [open, setOpen] = useState(false);

  const handleToggle = () => {
    setOpen(!open);
  };

  return (
    <div>
      <Button variant="contained" onCl ick={handleToggle}>
        Показать / Скрыть загрузку
      </Button>
      <Backdrop
        sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
        open={open}
      >
        <CircularProgress color="inherit" />
      </Backdrop>
    </div>
  );
}

Пояснения:

  • Свойство open контролирует видимость Backdrop.
  • sx позволяет быстро задавать стили, например цвет текста (color) и уровень слоя (zIndex), чтобы Backdrop перекрывал другие элементы.
  • Индикатор CircularProgress получает цвет через color="inherit", чтобы наследовать цвет текста Backdrop.

Стилизация и адаптация

Настройка цвета и прозрачности:

<Backdrop
  sx={{
    color: '#ff4081',
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
    zIndex: (theme) => theme.zIndex.drawer + 1
  }}
  open={open}
>
  <CircularProgress color="secondary" />
</Backdrop>
  • backgroundColor задаёт уровень прозрачности и цвет затемнения.
  • CircularProgress может использовать предопределённые цвета (primary, secondary) или кастомные через sx.

Анимация появления и скрытия:

MUI Backdrop по умолчанию поддерживает плавное появление через компонент Fade. Можно настроить длительность анимации:

import Fade from '@mui/material/Fade';

<Backdrop
  open={open}
  sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
  TransitionComponent={Fade}
  transitionDuration={500}
>
  <CircularProgress color="inherit" />
</Backdrop>
  • TransitionComponent позволяет использовать Fade, Grow или Slide.
  • transitionDuration задаёт скорость анимации в миллисекундах.

Асинхронная загрузка данных

Часто Backdrop используется для блокировки интерфейса во время загрузки данных с сервера:

function FetchDataButton() {
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    setLoading(true);
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/posts');
      const data = await response.json();
      console.log(data);
    } catch (error) {
      console.error('Ошибка загрузки данных:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <Button variant="contained" onCl ick={fetchData}>Загрузить данные</Button>
      <Backdrop sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }} open={loading}>
        <CircularProgress color="inherit" />
      </Backdrop>
    </>
  );
}

Особенности:

  • setLoading(true) активирует Backdrop до завершения асинхронной операции.
  • finally гарантирует скрытие Backdrop независимо от результата запроса.
  • Такой подход предотвращает множественные клики и улучшает UX.

Интерактивный индикатор с текстом

Можно добавлять текст или прогрессбар внутри Backdrop:

<Backdrop open={open} sx={{ color: '#fff', flexDirection: 'column', zIndex: (theme) => theme.zIndex.drawer + 1 }}>
  <CircularProgress color="inherit" />
  <span style={{ marginTop: 16 }}>Загрузка данных...</span>
</Backdrop>
  • flexDirection: 'column' располагает индикатор и текст вертикально.
  • marginTop создаёт отступ между индикатором и подписью.

Использование с контекстом и Redux

Для глобального состояния загрузки можно подключить Backdrop к состоянию приложения:

import { useSelector, useDispatch } from 'react-redux';
import { toggleLoading } from './loadingSlice';

function GlobalBackdrop() {
  const loading = useSelector(state => state.loading.value);
  const dispatch = useDispatch();

  return (
    <Backdrop sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }} open={loading}>
      <CircularProgress color="inherit" />
    </Backdrop>
  );
}
  • Подходит для случаев, когда множество компонентов инициируют загрузку данных.
  • Обеспечивает единый индикатор загрузки на уровне всего приложения.

Советы по производительности

  • Избегать одновременного открытия нескольких Backdrop на одной странице.
  • При большом контенте использовать Portal для Backdrop, чтобы не рендерить весь DOM заново.
  • Для минимального влияния на производительность применять shouldComponentUpdate или React.memo.

Этот подход позволяет создавать аккуратный, отзывчивый интерфейс с индикатором загрузки, полностью соответствующий стандартам Material Design, обеспечивая при этом контроль над стилями, анимациями и поведением компонента Backdrop.