はじめに
HTMLでファイルアップロードを実装する際、input type="file"
を利用します。React で以下のように書いた場合に、一度アップロードしたファイルを削除して再度同じファイルを選択しても反応しない事象が発生しました。
const [file, setFile] = useState<File | null>(null)
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedFile = e.target.files?.[0] || null
setFile(selectedFile)
}
const delFile = () => {
setFile(null)
}
return (
<>
<input type="file" onChange={handleChange} />
{file && <p onClick={delFile}>{file.name}</p>}
</>
)
この時、ファイルアップロード、ファイル選択削除、ファイルアップロードをすると選択できない事象がはっせいする。
原因
input type="file"
は 同じファイルを再選択しても onChange
イベントが発火しません。
これは、前回とまったく同じファイルが選択された場合、ブラウザ側が「変更なし」と判断してしまうためです。
対策
アップロード処理後や削除時に、input
の値をリセットして「状態を初期化」する必要があります。これにより、同じファイルを再度選択しても onChange
が発火するようになります。
onChange 内でリセット
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedFile = e.target.files?.[0] || null
setFile(selectedFile)
e.target.value = "" // ← ここでリセット
}
onClick でリセット
<input
type="file"
onChange={handleChange}
onClick={(e) => (e.currentTarget.value = "")}
/>
まとめ
input type="file"
は同じファイルを選択してもonChange
が発火しない- 対策は 値をリセットして初期化 すること
onChange
またはonClick
のどちらかでe.target.value = ""
を書けば解決
初歩的な挙動ではありますが、実装中に少し悩んでしまったので、同じ問題で困っている方の参考になれば幸いです。
コメント