[typescript] input type="file" image, preview, 미리보기(nextJs, React)

최영진·2023년 2월 8일
1

typescript

목록 보기
9/9
post-custom-banner

input type="file" image, preview, 미리보기

1. 첫 파일이 담기는 state 는 type이 File

  • image url만 생각하고 string으로 type을 주면 에러발생
  • File type은 File|undefined 기 때문에 선택되지 않음! 상황을 나타내기 위한
    null 값이 error 발생!
    그렇기 때문에 type 에 null 을 함께 준다.

2. onChangeImg

  • event type 설정
  • event.target.files 가 null 일 경우 허용되지 않기 때문에
    if 문으로 null 처리 해줌
  • 선택된 파일이 image 인지 한번더 검사하기 위해 type.substring을 이용하여 image 파일이 맞는지 한번더 확인.

3. preview, 미리보기

  • imgFile state가 변경되면 useEffect로 preview 실행
  • FileReader() 이용. 내장함수
  • reader.result의 type은 string | ArrayBuffer | null 이기 때문에 string | null 과 달라 error 발생! -> as string 처리
  • 선택되지 않았을 시 null 처리 (else)

4. input

  • type='file'
  • accept="image/*" -> image 파일만 선택하게 함.
  • src 에도 string|undefined 만 허용되기 때문에 as string 처리
  • 저장된 preview 는 이러한 형식으로 보여짐.
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYYAAAECCAYAAAD6oXArAAAMP2lDQ1BJQ0M......

~code~

// 1
const [imgFile, setImgFile] = useState<File | null>();
const [preview, setPreview] = useState<string | null>("");

// 2
const onChangeImg = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (event.target.files !== null) {
      const file = event.target.files[0];
      if (file && file.type.substring(0, 5) === "image") {
        setImgFile(file);
      } else {
        setImgFile(null);
      }
    }
  };

// 3
useEffect(() => {
    if (imgFile) {
      const reader = new FileReader();
      reader.onloadend = () => {
        setPreview(reader.result as string);
      };
      reader.readAsDataURL(imgFile);
    } else {
      setPreview(null);
    }
  }, [imgFile]);

// 4
<input
    name="img"
    type="file"
    accept="image/*"
    onChange={onChangeImg}
    className="hidden"
/>
      
<img src={preview as string} />
profile
안녕하시오.
post-custom-banner

0개의 댓글