혹시나 잘못된 개념 전달이 있다면 댓글 부탁드립니다. 저의 성장의 도움이 됩니다
프로젝트 컴포넌트 구현 전 기능 테스트 용으로 작성한 코드이다.
<input type="file">
를 화면에 노출되지 않도록 CSS 적용하고, <img>
태그 클릭하면 활성화 되도록 했다.
미리보기 기능은 업로드된 파일으로 임시 url을 생성하여 표시한다.
url을 생성할 방법은 2가지가 있는데 그 중 URL 객체로 구현하는 방법이다.
import { useState, useRef } from "react";
import axios from "axios";
import styled from "styled-components";
const SImg = styled.img`
width: 250px;
height: 200px;
object-fit: cover; // 비율 조정
border: 1px solid black;
`;
const SImgInput = styled.input`
display: none;
`;
const ImgUploader = () => {
const [fileURL, setFileURL] = useState<string>("");
const [file, setFile] = useState<FileList | null>();
const imgUploadInput = useRef<HTMLInputElement | null>(null);
const onImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
setFile(event.target.files);
const newFileURL = URL.createObjectURL(event.target.files[0]);
setFileURL(newFileURL);
}
};
const onImageRemove = (): void => {
URL.revokeObjectURL(fileURL);
setFileURL(""); // 렌더링 이미지 초기화
setFile(null);
};
const submitHandler = async (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
/** 서버통신 */
const formData = new FormData();
if (file) {
formData.append("file", file[0]);
try {
const response = await axios.post("/api/upload", formData, {
headers: { "content-type": "multipart/form-data" },
});
} catch (error: any) {
console.log("이미지업로드 에러 발생");
throw new Error(error);
}
} else {
alert("업로드할 이미지가 없습니다");
}
};
return (
<>
<SImg
src={
fileURL
? fileURL
: "https://cdn-icons-png.flaticon.com/512/1555/1555492.png"
}
alt=""
></SImg>
<label htmlFor="img">이미지 업로드</label>
<SImgInput
type="file"
id="img"
accept="image/*"
required
ref={imgUploadInput}
onChange={onImageChange}
></SImgInput>
<button
type="button"
onClick={(event) => {
event.preventDefault();
if (imgUploadInput.current) {
imgUploadInput.current.click();
}
}}
>
이미지 변경 버튼
</button>
<button type="button" onClick={onImageRemove}>
제거 버튼
</button>
<button onClick={submitHandler}>submit</button>
</>
);
};
export default ImgUploader;
타입스크립트 기초만 겨우 듣고 작성한 코드라서 잘못된 부분이 있을 수 있다.
와이어프레임 작성 전 테스트용으로 구현한 것이라 실제 프로젝트에는 많은 변동이 될 예정이다.