React: Görüntü Yüklemeyi Özel Bir Bileşenle İşleme

Jan 30 2023
React'te Sorunsuz Bir Görüntü Yükleme Deneyimi Oluşturma
Kısa bir süre önce, projemdeki yanıp sönen görüntüler beni hayal kırıklığına uğratmıştı. Bu yüzden, resim yükleme sırasında bir döndürücü ve indirme başarısız olduğunda bir yer tutucu gösterebilen bir bileşen oluşturdum.

Kısa bir süre önce, projemdeki yanıp sönen görüntüler beni hayal kırıklığına uğratmıştı. Bu yüzden, resim yükleme sırasında bir döndürücü ve indirme başarısız olduğunda bir yer tutucu gösterebilen bir bileşen oluşturdum. Hemen, uygulamayı kullanmanın ne kadar kolaylaştığını fark ettim ve hatta yönetim ekibinden bazı övgüler aldım. O yazıda, bileşeni adım adım açıklayarak çözümümü sizinle paylaşacağım.

Haydi dalalım!

Nihai Sonucumuz

Her şeyden önce, sahne ilan edelim

Dürüst olmak gerekirse, her şey oldukça kolay. Bileşenimiz sadece üç durumda olabilir: Resim gösteriliyor, loader gösteriliyor ve hata gösteriliyor. Bu durumlar için sadece 3 ana donanıma ihtiyacımız var: imageSrc, showLoader, showPlaceholder.Şimdi bunları açıklayalım!

// I prefer to pass additional classes to my component that way
// Feel free to delete it in your case :)
export type ImagePreviewClasses = {
  root?: string;
  image?: string;
  loader?: string;
  placeholder?: string;
};

export type ImagePreviewProps = {
  imageSrc?: string | null;
  className?: string;
  classes?: ImagePreviewClasses;
  showLoader?: boolean;
  showPlaceholder?: boolean;
// Union to pass additional props for the root tag of component
} & React.HtmlHTMLAttributes<HTMLDivElement>;

Biri yükleme ve diğeri hata için olmak üzere iki durum bildirerek başlamalıyız. Ondan sonra imajımızı nasıl yükleyeceğimize karar vermeliyiz. İçinde bir HTML öğesi oluşturmanızı useEffectve ardından gerekli tüm işleyicileri ona eklemenizi şiddetle tavsiye ederim. İşte böyle görünüyor:

// Feel free to use something like useBooleanState or useToggle
  const [loaded, setLoaded] = useState(false);
  const [error, setError] = useState(false);

  const setLoadingTrue = useCallback(() => {
    setLoaded(true);
  }, []);

  const setErrorTrue = useCallback(() => {
    setError(true);
  }, []);

  useEffect(() => {
    const img = new Image();

    if (imageSrc) {
      // Now browser will start downloading image
      img.src = imageSrc;

      // In case imageSrc changed after loading or error
      setLoaded(false);
      setError(false);

      // Subscribing on image load and error
      img.addEventListener("load", setLoadingTrue);
      img.addEventListener("error", setErrorTrue);
    }

    // Don't forget to unsubscribe, we don't need memory leaks)
    return () => {
      img.removeEventListener("load", setLoadingTrue);
      img.removeEventListener("error", setErrorTrue);
    };
  }, [imageSrc, setLoadingTrue, setErrorTrue]);

Bileşenimizin yalnızca üç durumu olduğunu hatırlıyor musunuz? Bence onlar için ekstra değişkenler oluşturmalıyız. İşte buradalar:

const imgLoaded = loaded && !error;
  const imgLoading = imageSrc && !loaded && !error;
  const imgFailed = !imageSrc || error;

// clsx is a function for classNames manipulation
<div {...rootProps} className={clsx("ImagePreview", className, classes?.root)}>
  // If we want to showLoader and image is loading
  {showLoader && imgLoading && (
    <div className={clsx("ImagePreview__loader", classes?.loader)}>
      {/* You can place here any spinner you like) */}
      <BounceLoader color="#a8a8a8" />
    </div>
  )}

  // If we want to show placeholder and image loading failed
  {showPlaceholder && imgFailed && (
    <div className="ImagePreview__placeholder">
      <svg width="40px" height="40px" viewBox="0 0 24 24">
        <path
          d="M22 3H2v18h20v-2h-2v-2h2v-2h-2v-2h2v-2h-2V9h2V7h-2V5h2V3zm-2 4v2h-2v2h2v2h-2v2h2v2h-2v2H4V5h14v2h2zm-6 2h-2v2h-2v2H8v2H6v2h2v-2h2v-2h2v-2h2v2h2v-2h-2V9zM6 7h2v2H6V7z"
          fill="#000000"
        />
      </svg>
    </div>
  )}

  // Div hodling our image on the background
  <div
    className={clsx("ImagePreview__image", classes?.image, {
      ImagePreview__image_loaded: imgLoaded
    })}
    style={
      imageSrc && !error
        ? {
            backgroundImage: `url(${imageSrc})`
          }
        : {}
    }
  />
</div>

Okuduğunuz için teşekkürler!

Umarım bu makaleyi faydalı bulmuşsunuzdur. Herhangi bir sorunuz veya öneriniz varsa, lütfen yorum bırakın. Geri bildirimleriniz daha iyi olmama yardımcı oluyor.

Abone olmayı unutmayın⭐️

PlainEnglish.io'da daha fazla içerik . Haftalık ücretsiz bültenimize kaydolun . Bizi Twitter , LinkedIn , YouTube ve Discord'da takip edin .

Yazılım başlangıcınızı ölçeklendirmekle ilgileniyor musunuz ? Devreyi kontrol edin .