<iuput type='file'>
를 사용하면서 하나가 아닌 여러 파일을을 받을 때 데이터를 filter를 사용하거나, map을 사용하려고 했지만, not function이라는 경고와 함께 메소드가 실행되지 않는 것을 볼 수 있었다.
해당 데이터가 배열이 아니라는 말인데, 데이터가 어떻게 들어가고 나가는지 정리하고 기록해두려한다.
const handleUploadFile = (e) => {
setUploadFile(uploadFiles);
};
// html
<input type="file" multiple onChange={(e) => {handleUploadFile(e.target.files)}}/>
위와 같이 <input>
에 여러 파일이 들어가고, handleUploadfile
이라는 함수에 이벤트 객체가 들어가게 된다. 해당함수는 uploadfile이라는 state로 저장되고, 다시 mapping되어 사용자에게 보여지는 형식이다.
하지만 위와 같이 코드를 짜게 되면 아래와 같은 오류가 생기게 된다.
왜 이렇게 되는 것일까? 하여 해당 이벤트에 생기는 객체를 살펴볼 필요가 있었다. 하여 콘솔을 찍어보니 아래와 같은 fileList가 있는것을 볼 수 있었다.
const handleUploadFile = (e) => {
console.log(e.target.files)
};
// html
<input type="file" multiple onChange={(e) => {handleUploadFile(e)}}/>
난 이걸 보고나서 객체형태로 들어가는줄 알고, 해당 데이터를 e.target.files.FileList
로 접근했지만, undefined가 나오게 되었다. 그럼 배열도 객체도 아닌 뭐란 말인가..
결론은 이벤트 객체의 FileList는 배열이 아닌 file 객체를 여러개를 담고 있는 유사배열 객체(Array-like)이다. 위처럼 이벤트 핸들러에서 input엘리먼트의 .files로 FileList 배열객체를 참조할 수 있다.
그렇기 때문에 .files[0]접근이나 .length는 사용가능하나, 배열이 아니기 때문에 map, filter, foreach 등을 사용할 수 없는 것이다.
그렇다면 해당 데이터를 배열로 변환후 사용할 수는 없을까?
FileList에 해당 메소드를 사용할 수 없는 이유를 알았다면 해결방법은 간단하다. 해당 데이터를 배열의 형태를 바꿔주면 가능하다는 뜻이다.
Array.from으로 유사배열 객체를 Array로 변환해주면 되겠다.
const handleUploadFile = (e) => {
const uploadFile = Array.from(e.target.files)
setUploadFile(uploadFiles);
};
// html
<input type="file" multiple onChange={(e) => {handleUploadFile(e)}}/>