리뷰 작성을 하는 창에서 사진 3개를 첨부할 수 있도록 하고, 사진 미리보기를 띄워주도록 해야했다.
이번 포스팅은 단순 기능 구현과 공부한것들의 기록이고, 다음 포스팅에서 서버와의 연결을 기록하도록 하겠다.
✨알아야할것
FileReader
- Web API
- 웹 브라우저에서 제공하는 API
- 개발자가 브라우저 상에 쉽게 개발할 수 있도록 도와주는 객체의 모음
- 파일을 읽을 수 있게 해주는 객체
- File, Blob 객체를 핸들링할 때 사용됨.
- Blob : 이미지, 사운드, 비디오와 같은 멀티미디어 데이터 다룰때 사용
- 데이터의 크기(Byte) 및 데이터 송수신을 위한 작은 Blob 객체로 나누는 등의 작업에 사용함.
- Blob : 이미지, 사운드, 비디오와 같은 멀티미디어 데이터 다룰때 사용
- 위의 객체를 사용해 특정 파일을 읽어들여 JS에서 파일에 접근할 수 있도록 도와줌
readAsDataURL
- 파일을 URL로 만들 수 있음, 파일 정보를 주소처럼 사용할 수 있다.
- 바이너리 파일을 읽어들일 때 사용됨.
- base64로 이루어진 데이터를 반환받을 수 있음.
+)Base64
바이너리 데이터를 문자 코드에 영향 받지 않는 공통 ASCII 문자로 표현하기 위해 만들어진 인코딩
Promise
- JS에서 비동기 처리에 활용되는 객체. (순차적X, 다음 코드 먼저 실행)
- 서버에 데이터를 요청했을 때, 데이터가 모두 받아오기 전에 웹에 출력하려고 할 때 발생하는 오류를 방지하기 위해 활용
- 콜백 함수 인자인 resolve를 실행하면 이행된(Fulfilled) 상태 (완료된 상태)
- reject는 호출 시 실패(Rejected) 상태
버튼 꾸미기
- <input>버튼이 생겨서 display:none으로 숨기고, <label>태그를 사용할 수 있음
What is <label> 태그?
- 폼의 양식에 이름을 붙이는 태그
- 주요 속성은 for
- label의 for 값과 양식의 id 값이 같으면 연결된다.
- label을 클릭하면, 연결된 양식에 입력할 수 있도록 하거나, 체크를 하거나, 체크를 해제함
✨작성한 코드
<label htmlFor="UploadImg1" className={styles.UploadImgButton}>
{imageUploaded ? null : <img src="/img/plusicon.png" className={styles.plusImage} />}
</label>
<input
type="file"
accept="image/*"
id="UploadImg1"
onChange={FileUploadHandler}
/>
{imageSrc && <img src={imageSrc} alt="preview-img" className={styles.uploadedImage} />}
< input type="file" accept="image/*" />
를 설정하면 컴퓨터의 파일 중, 이미지의 형식만 업로드 할 수 있다.
<label htmlFor="UploadImg1">, <input id="UploadImg1">
위에서 말했듯이, label의 for값과 양식의 id의 값이 같으면 연결을 할 수 있다.
리액트에서는 label의 for를 htmlFor로 작성을 해주어야 한다. 둘의 아이디를 똑같이 맞추어주면 연결이 된다.
위에서 설정한 + 그림을 누르면 파일 선택 창이 열린다.
{imageUploaded ? null : <img src="/img/plusicon.png"/>}
이 코드는 이미지가 업로드 되었는지의 여부를 통해 + 이미지를 보여주고 숨기는 코드이다.
이미지가 첨부되었을때 아이콘은 숨겨지고, 미리보기 이미지만 띄워주게 하기 위해서이다.
삼항연산자를 통해 imageUploaded가 참 (이미지가 업로드 되었다)면 null을 반환함으로써 +를 보여주지 않는다.
const encodeFileToBase64 = (fileBlob) => {
//객체 생성
const reader = new FileReader();
reader.readAsDataURL(fileBlob);
return new Promise((resolve) => {
reader.onload = () => {
setImageSrc(reader.result);
resolve();
};
});
};
파일을 읽을 수 있는 FileReader객체를 생성한다. readAsDataURL을 통해 파일을 URL로 만들어준다.
그리고 이를 ImageSrc에 저장한다.
{imageSrc && <img src={imageSrc} alt="preview-img" />}
이렇게 되면 위의 코드가 설명이 되겠다.
imageSrc가 존재할 경우 미리보기 이미지를 띄워주는 코드이다.
const FileUploadHandler = (e) => {
const file = e.target.files[0];
if (file) {
encodeFileToBase64(file).then(() => {
setImageUploaded(true); // + 아이콘 숨기고 보여주기 위한 부분
setImageFile1(file); // 이미지 파일 설정 (저장) 서버 전송을 위한 부분
});
} else {
setImageSrc('');
setImageUploaded(false); // + 아이콘
setImageFile1(null);
}
};
const file = e.target.files[0];
e.target.files 배열에서 input에서 선택한 파일의 정보를 얻어온다.
💡개발 도중 발생한 문제 상황들
문제 01 - 파일 업로드 상황에서 ‘취소’를 눌렀을 경우 오류 발생
const FileUploadHandler = (e) => {
const file = e.target.files[0];
if (file){
encodeFileToBase64(file);
} else {
setImageSrc('');
}
}
이렇게 if문으로 해결했다.
문제 02 - 이미지 파일 업로드 3개를 해야함. (각자 따로)
각 이미지 상태를 담는 state를 3개 만들었다.
나중에 최적화 해보도록 하겠다.
참고 자료
'❄️ React' 카테고리의 다른 글
[React] map() 메서드, map() 함수란? (3) | 2024.09.11 |
---|---|
[React/Google Map] 구글맵 기본 마커 지우기 (1) | 2023.11.14 |
[http-server] 페이지 로드하기 (0) | 2023.11.14 |
[http-server] 이 시스템에서 스크립트를 실행할 수 없으므로~ 오류 해결 (1) | 2023.11.13 |
[React] axios 서버 연결중 request failed with status code 405 (0) | 2023.08.23 |