[React.js] useRef로 이미지 업로드를 하며 알게된 것들
책을 보며 useRef를 봤을 때 크게 와닿지 않았다.
적당히 재 랜더링 방지해주는구나..
컴포넌트가 랜더링이 돼도 계속 남아있으니 메모리를 차지하겠구나.. 하고 넘어갔다.
회사의 신규 프로젝트에서 프론트엔드 & 백엔드 간 이미지 파일을 전송하는 기능이 필요해서 구글링을 해보니 언제 쓰는건가 궁금했던 useRef를 쓰더라.
const ButtonInputImage = (props) => {
const [imgFile, setImgFile] = useState("");
const imgRef = useRef();
const textRef = useRef();
const saveImgFile = () => {
const file = imgRef.current.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setImgFile(reader.result);
};
};
console.log("ButtonInputImage 랜더링");
return (
<>
<CenterIdv>
<Img src={imgFile ? imgFile : `/img/logo192.png`} alt="프로필 이미지" />
<Label htmlFor="imageUpload">{props.title}</Label>
<Input
type="file"
id="imageUpload"
accept="image/*"
onChange={saveImgFile}
ref={imgRef}
/>
</CenterIdv>
</>
);
};
1. input 핸들링을 위한 useRef() 참조 객체와 img 핸들링을 위한 useState를 선언한다.
2. <input>에 ref prop으로 imgRef를 전달한다
-> imgRef의 current 속성을 통해 <input>엘레먼트에 접근할 수 있다.
3. onChange prop으로 saveImgFile 함수를 불러온다
4. 함수 안에서 imgRef 참조 객체에 접근한다. 필요한 데이터는 current.files에 있다.
5. FileReader() 의 객체 const reader를 생성한다.
-> FileReader : 웹이 비동기적으로 데이터를 읽기 위하여 파일을 가리키는 File객체를 이용해 파일 내용을 읽거나 저장시키는 함수.
6. FileReader()의 메서드 중 readAsDataURL()로 파일을 읽는다.
-> 읽은 후 console.log(reader)를 찍어봤는데 사진 정보가 어디 들어가는지 몰라서 찾아보니 바이너리 파일을 Base64 Encode 문자열로 반환하는 메소드라고 한다.
** Base64 는 0,1로 이루어진 Binary 데이터를 아스키 코드 일부와 일대일로 매칭되는 문자열로 단순 치환되는 인코딩 방식이라고 함.. 해당 값은 reader.result에 저장된다.
7. FileReader() 이벤트핸들러 중 onloadend를 활용해 동작이 성공적으로 완료됐을 때 useState 실행 함수에 reader.result를 넣어 imgFile의 상태를 변환시켜준다.
8. imgFile이 변경되면 useState에 의해 재랜더링이 이루어지고 Img태그의 src에서 result 값을 처리해준다.
-> imgFile? 은 삼항연산자로써 imgFile이 truethy 하면 컬럼(:)의 좌측을 실행하고 falsy하면 우측을 실행한다.
-> falsy는 불리언 문맥에서 false로 평가되는 값으로 0, false, null, undefined 는 false 값으로 치환된다.
-> 어떤 값이 들어온다면 truthy하기 때문에 true로 치환된다.
-> 즉, result 값이 안 들어온 상태면 이미지를 기본 이미지로 올리고, result 값이 truthy하게 변하면 result 값을 src에 넣어주면 이미지가 로딩된다.
성공적으로 이미지를 로딩한 후 실제로 useRef의 함수는 해당 객체의 변화가 없는 상태에서 재랜더링 할 때 실행이 안 되는지 콘솔을 찍어봤다.
재랜더링을 일으키기 위해 input에다가 useState를 걸어놓고 타이핑 할 때마다 재랜더링 되게 해놨다.
기능을 구현하는데에는 얼마 걸리지 않는데 어떤 프로세스로 동작하는지 아는것은 꼬꼬무처럼 질문이 꼬리에 꼬리를 물어버린다. 그래서 공부하는 재미가 있다.