React에서 동일한 파일 업로드 구현
React에서 파일 업로드 구현하는 방법은 아래 포스팅에서 소개했으나 회사 프로젝트에서 파일 업로드를 구현하는 과정에서 한 가지 문제가 발생했습니다.
이번 포스팅에서 설명하는 소스 코드가 이해되지 않는다면 아래 포스팅을 꼭 읽어주세요.
동일한 파일을 업로드하는 경우 input 태그의 onChange 이벤트 핸들러 함수가 정상적으로 동작하지 않는 문제였는데요.
웹 브라우저에서 버튼을 클릭하면 위 사진처럼 파일 탐색기 창이 열립니다. 파일 탐색기 창에서 파일 선택 후 열기 버튼을 클릭하면 선택된 파일을 서버에 바로 업로드해야 하는 작업이 존재했습니다.
동일한 파일을 두 번 이상 업로드했을 경우 BackEnd에서 파일명 중복 체크하는 로직을 구현해야 하는데, FrontEnd에서 동일한 파일을 연속해서 선택했을 때, input 태그의 onChange 이벤트 핸들러 함수가 동작하지 않았습니다.
다음 예제 소스를 통해 onChange 이벤트 핸들러 함수가 정상적으로 동작했던 시나리오와 동작하지 않았던 시나리오를 살펴봅시다.
다음 예제는 파일 탐색기에서 선택한 파일의 이름을 콘솔에 출력하며 codesandbox에서 테스트 가능합니다.
import React, { Component } from "react";
import ReactDOM from "react-dom";
class FileUploadButton extends Component {
handleFileUpload = (event) => {
if (event.target.files.length > 0) {
console.log(event.target.files[0].name);
}
};
render() {
return (
<React.Fragment>
<input
ref="fileInput"
onChange={this.handleFileUpload}
type="file"
style={{ display: "none" }}
/>
<button onClick={() => this.refs.fileInput.click()}>Upload File</button>
</React.Fragment>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<FileUploadButton />, rootElement);
이벤트 핸들러 함수가 정상적으로 동작
- 파일 업로드 버튼 클릭
- 파일 탐색기 창에서 TestFile_A.jpg 파일 선택 후 열기 버튼 클릭
- 파일 탐색기 창에서 TestFile_B.jpg 파일 선택 후 열기 버튼 클릭
- 파일 탐색기 창에서 TestFile_A.jpg 파일 선택 후 열기 버튼 클릭
이벤트 핸들러 함수가 동작하지 않음
- 파일 업로드 버튼 클릭
- 파일 탐색기 창에서 TestFile_A.jpg 파일 선택 후 열기 버튼 클릭
- 파일 탐색기 창에서 TestFile_A.jpg 파일 선택 후 열기 버튼 클릭
위 시나리오처럼 동일한 파일을 연속해서 선택한 경우 "TestFile_A.jpg"가 콘솔에 두 번 출력될 거라 예상했지만, 단 한 번만 출력되었습니다.
해결 방법
위 문제가 발생했던 원인은 추측이지만 동일한 파일을 선택하는 경우 JavaScript가 input 태그의 onChange 이벤트 핸들러 함수를 동작하지 않도록 했기 때문이라고 생각됩니다.
onChange 이벤트 핸들러 함수가 정상적으로 동작하도록 하기 위해서는 input 태그에 onClick 이벤트 핸들러 함수를 추가하고 event.target.value를 빈 값('') 또는 null로 초기화하는 코드를 작성합니다.
import React, { Component } from "react";
import ReactDOM from "react-dom";
class FileUploadButton extends Component {
handleFileUpload = (event) => {
if (event.target.files.length > 0) {
console.log(event.target.files[0].name);
}
};
handleClick = (event) => {
event.target.value = null;
};
render() {
return (
<React.Fragment>
<input
ref="fileInput"
onChange={this.handleFileUpload}
onClick={this.handleClick}
type="file"
style={{ display: "none" }}
// multiple={false}
/>
<button onClick={() => this.refs.fileInput.click()}>Upload File</button>
</React.Fragment>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<FileUploadButton />, rootElement);
event.target.value를 null로 할당하는 이벤트 핸들러 함수를 input 태그의 onClick에 추가하고 동일한 파일을 연속해서 선택하면 onChange 이벤트 핸들러 함수가 정상적으로 동작하는 것을 확인할 수 있습니다.
※ 주의사항
위 해결 방법은 크롬에서는 정상적으로 동직하지만, 다른 브라우저에서는 동작하지 않을 수 있습니다.
참고
'React > React 문법' 카테고리의 다른 글
[React]Element 크기 조절을 감지하는 방법 (0) | 2023.01.09 |
---|---|
[React]파일 업로드 구현 (2) | 2022.07.11 |
[React]React Hook에서 Throttle, Debounce 사용 (1) | 2021.11.30 |
[React]React Hook setState에 함수 전달 (0) | 2021.11.22 |
[React]useEffect Hook에서 async await를 사용하여 API 호출 (1) | 2021.11.18 |
댓글