티스토리 뷰

import React, { useCallback, useEffect, useState } from 'react';
import PropTypes from 'prop-types';

/*
 * ImageWidthPlaceholder
 * 이미지 로드 전 대체 이미지 표시
 */
const ImageWithPlaceholder = ({ width, height, src, alt, onClick }) => {
  const [source, setSource] = useState('/images/img_profile_edit_nodata.png'); // 기본 이미지
  const [imageWidth, setImageWidth] = useState(width);
  const [imageHeight, setImageHeight] = useState(height);

  const handleLoad = useCallback((imgSrc) => {
    setSource(imgSrc);
    setImageWidth(null);
    setImageHeight(null);
  }, []);

  useEffect(() => {
    if (!src) {
      return false;
    }

    const image = new Image();

    if (src instanceof File) {
      const reader = new FileReader();
      reader.readAsDataURL(src);
      reader.addEventListener(
        'load',
        () => {
          image.src = reader.result;
        },
        false
      );
    } else {
      image.src = src;
    }
    image.onload = () => handleLoad(image.src);

    return () => image.removeEventListener('onload', handleLoad(image));
  }, [src]);

  return (
    <img
      src={source}
      data-src={src}
      alt={alt}
      onClick={onClick}
      width={imageWidth}
      height={imageHeight}
    />
  );
};

ImageWithPlaceholder.defaultProps = {
  width: undefined,
  height: undefined,
  src: null,
  onClick: undefined,
};

ImageWithPlaceholder.propTypes = {
  width: PropTypes.number,
  height: PropTypes.number,
  src: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(File)]),
  alt: PropTypes.string.isRequired,
  onClick: PropTypes.func,
};

export default ImageWithPlaceholder;

 

사용법

<ImageWithPlaceholder src={imgUrl}></ImageWithPlaceholder>

외부 이미지 서버 또는 자체적 이미지 뷰어 API 등 src로 들어가는 이미지를 못 불러 올 경우 기본 이미지로 대체하는 Component이다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함