본문 바로가기
Front End

Custom File Input 처리시 파일이 변경 되지 않는 에러

by 코딩파이 2024. 10. 1.
똑똑한개발자 내부 코드리뷰의 외부 공개용 재정리 파일입니다. @24.06.03

 

파일 업로드를 구현할 때 <Input type="file" /> 을 직접적으로 사용하면 CSS 변경에 제약이 커서

따로 UI를 그린 후 input창을 따로 핸들링하는 형태로 많이 사용했습니다.

 

이렇게 코드를 짰을 때 동일한 파일을 업로드 할 떄 파일 상태가 변하지 않는 문제가 있습니다.

예시 코드는 아래와 같습니다.

  const inputFileRef = useRef<HTMLInputElement>(null);

  const onClickUploadButton = useCallback(() => {
      inputFileRef.current?.click()
    }, []);

  const onChangeUploadFile = useCallback((
    e: ChangeEvent<HTMLInputElement>
  ) => {
      if (!e.target?.files) return;

      const { files } = e.target;
      setValidateUploadFile(files);
    },
    [setValidateUploadFile],
  );

return (
  <>
  ...
    <Input
      type="file"
      display="none"
      ref={inputFileRef}
      onChange={onChangeUploadFile}
    />


    <Button onClick={onClickUploadButton}
    >
      내 PC
    </Button>

  </>

)

 

하단 버튼을 누르면 <Input type="file" /> 를 클릭 했을때와 동일한 파일 선택 UI가 표출됩니다.

파일을 선택했다면 onChange 핸들러가 발동합니다.

문제는 A 파일 선택 상태에서 -> 삭제 후 -> 다시 A 파일을 선택하면 동일한 파일이 존재한다고 인식하여 onChange 핸들러가 작동하지 않습니다.

 

이를 해결하기 위해 onChange가 작동할 때 마다 컴포넌트가 변경되었다는 것을 강제로 알려주기 위해 key값을 추가했습니다.

 

  const inputFileRef = useRef<HTMLInputElement>(null);
  const [inputKey, setInputKey] = useState(0);

  const onClickUploadButton = useCallback(() => {
      inputFileRef.current?.click()
    }, []);

  const onChangeUploadFile = useCallback((
    e: ChangeEvent<HTMLInputElement>
  ) => {
      ...
      // 파일이 변경될 떄 마다 key 값을 변경시킵니다.
      setInputKey((prev) => prev + 1);
    },
    [setValidateUploadFile],
  );

return (
  <>
  ...
    <Input
      type="file"
      {/* key 추가 */}
      key={inputKey}
      display="none"
      ref={inputFileRef}
      onChange={onChangeUploadFile}
    />


    <Button onClick={onClickUploadButton}
    >
      내 PC
    </Button>

  </>

)

 

이 방식 외에도 onChange가 일어날 때 마다 input의 value를 강제로 비워주는 여러 방법으로 에러를 해결할 수 있습니다.