← Назад к вопросам

Как обработать отсутствие изображения?

1.7 Middle🔥 141 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Обработка отсутствия изображения в React приложении

Отсутствие или ошибки загрузки изображений - частая проблема в веб-приложениях. Правильная обработка улучшает пользовательский опыт, предотвращает broken layouts и показывает профессионализм.

Основной подход с использованием Next.js Image

Next.js предоставляет встроенный компонент Image с оптимизацией и поддержкой fallback:

import Image from "next/image";
import { useState } from "react";

function ProfileImage({ src, alt = "Profile" }) {
  const [hasError, setHasError] = useState(false);
  const [isLoading, setIsLoading] = useState(true);

  const fallbackSrc = "/images/placeholder-user.png";

  return (
    <div className="relative w-24 h-24 bg-surface-secondary rounded-lg">
      <Image
        src={hasError ? fallbackSrc : src}
        alt={alt}
        fill
        className="object-cover rounded-lg"
        onError={() => setHasError(true)}
        onLoadingComplete={() => setIsLoading(false)}
        priority={false}
      />
      {isLoading && (
        <div className="absolute inset-0 bg-surface-tertiary animate-pulse rounded-lg" />
      )}
    </div>
  );
}

Расширенная обработка с Intersection Observer

Для оптимизации производительности при множестве изображений используй lazy loading:

function LazyImage({ src, alt, fallback = "/placeholder.png" }) {
  const [imageSrc, setImageSrc] = useState(fallback);
  const [isLoading, setIsLoading] = useState(true);
  const imgRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const img = new Image();
            img.onload = () => {
              setImageSrc(src);
              setIsLoading(false);
            };
            img.onerror = () => {
              setImageSrc(fallback);
              setIsLoading(false);
            };
            img.src = src;
            observer.unobserve(entry.target);
          }
        });
      },
      { rootMargin: "50px" }
    );

    if (imgRef.current) {
      observer.observe(imgRef.current);
    }

    return () => observer.disconnect();
  }, [src, fallback]);

  return (
    <div
      ref={imgRef}
      className="relative w-full h-full bg-surface-secondary"
    >
      <img
        src={imageSrc}
        alt={alt}
        className={cn(
          "w-full h-full object-cover transition-opacity",
          isLoading ? "opacity-0" : "opacity-100"
        )}
      />
      {isLoading && (
        <div className="absolute inset-0 bg-gradient-to-r from-surface-secondary via-surface-tertiary to-surface-secondary animate-pulse" />
      )}
    </div>
  );
}

Обработка с srcSet для адаптивных изображений

function ResponsiveImage({ src, alt }) {
  const [error, setError] = useState(false);

  return (
    <picture>
      <source
        srcSet={`${src}?w=640 640w, ${src}?w=1280 1280w`}
        media="(max-width: 768px)"
      />
      <source
        srcSet={`${src}?w=1920 1920w`}
        media="(min-width: 769px)"
      />
      <img
        src={error ? "/placeholder.png" : src}
        alt={alt}
        onError={() => setError(true)}
        className="w-full h-auto"
      />
    </picture>
  );
}

Интеграция с retry логикой

function RobustImage({ src, alt, maxRetries = 3 }) {
  const [currentSrc, setCurrentSrc] = useState(src);
  const [retries, setRetries] = useState(0);
  const [failed, setFailed] = useState(false);

  const handleError = () => {
    if (retries < maxRetries) {
      setTimeout(() => {
        setCurrentSrc(`${src}?retry=${retries + 1}`);
        setRetries(retries + 1);
      }, 1000 * (retries + 1));
    } else {
      setFailed(true);
    }
  };

  if (failed) {
    return (
      <div className="w-full h-full bg-surface-secondary flex items-center justify-center">
        <div className="text-center">
          <div className="text-2xl mb-2">No image</div>
          <p className="text-text-secondary text-sm">{alt}</p>
        </div>
      </div>
    );
  }

  return (
    <img
      src={currentSrc}
      alt={alt}
      onError={handleError}
      className="w-full h-auto"
    />
  );
}

Best Practices

  1. Всегда используй alt атрибут - важно для доступности и SEO
  2. Предоставь placeholder - skeleton, blur или default image
  3. Обработай ошибку сети - retry логика с экспоненциальной задержкой
  4. Используй Next.js Image - автоматическая оптимизация формата и размера
  5. Lazy load при необходимости - улучшает производительность на мобильных
  6. Логируй ошибки - отправляй в аналитику для мониторинга

Правильная обработка отсутствия изображений показывает внимание к деталям и улучшает пользовательский опыт.

Как обработать отсутствие изображения? | PrepBro