ReactJS文件上传需两次选择才生效问题求助
问题描述
首次点击按钮选择文件并上传成功后,再次选择文件时需点击choose a file两次才能生效,否则会显示No file selected.。
相关代码
const FactoryContactUpload = () => { const [selectedFile, setSelectedFile] = useState(null); const handleFileChange = (event) => { // Handle the file change event const file = event.target.files[0]; setSelectedFile(file); }; const handleFileClick = (event) => { setShowAlert(false); }; const handleUpload = async () => { // Handle the upload event if (selectedFile) { const formData = new FormData(); formData.append("file", selectedFile); const token = await acquireTokenSilent(instance); apiClient .post("/factorycontact/upload", formData, { headers: { "Content-Type": "multipart/form-data", Authorization: `Bearer ${token}`, }, }) .then((response) => { // Handle the API response setShowAlert(true); setAlertType("success"); setAlertMessage(response.data.message || ""); }) .catch((error) => { // Handle errors setShowAlert(true); setAlertType("error"); setAlertMessage(error.response?.data?.message || "An error occurred"); }); } else { setShowAlert(true); setAlertType("info"); setAlertMessage("No file selected."); } }; return ( <div> <> <input type="file" onChange={handleFileChange} onClick={handleFileClick} /> <button onClick={handleUpload}>Upload</button> <br /> <br /> </> {showAlert && <Alert type={alertType} message={alertMessage} />} </div> ); };
问题原因
核心问题是上传完成后未重置文件输入框的状态:
- 上传成功后,
selectedFile状态仍保留着旧文件的引用,同时浏览器文件输入框的内部值也未清空; - 当用户再次选择同一文件时,浏览器会判定输入框值未发生变化,不会触发
onChange事件;即使选择不同文件,也会因为组件状态与DOM状态不一致,导致文件选择逻辑异常。
解决方案
需要在上传成功后同步清空文件状态并重置输入框DOM,确保下次选择文件时onChange事件能正常触发。修改后的代码如下:
import { useState, useRef } from 'react'; const FactoryContactUpload = () => { const [selectedFile, setSelectedFile] = useState(null); // 添加ref用于获取文件输入框DOM const fileInputRef = useRef(null); // 补充原代码缺失的状态定义 const [showAlert, setShowAlert] = useState(false); const [alertType, setAlertType] = useState(''); const [alertMessage, setAlertMessage] = useState(''); const handleFileChange = (event) => { const file = event.target.files[0]; setSelectedFile(file); }; const handleFileClick = (event) => { setShowAlert(false); }; const handleUpload = async () => { if (selectedFile) { const formData = new FormData(); formData.append("file", selectedFile); const token = await acquireTokenSilent(instance); apiClient .post("/factorycontact/upload", formData, { headers: { "Content-Type": "multipart/form-data", Authorization: `Bearer ${token}`, }, }) .then((response) => { // 上传成功后清空文件状态并重置输入框 setSelectedFile(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } // 提示信息更新 setShowAlert(true); setAlertType("success"); setAlertMessage(response.data.message || ""); }) .catch((error) => { setShowAlert(true); setAlertType("error"); setAlertMessage(error.response?.data?.message || "An error occurred"); }); } else { setShowAlert(true); setAlertType("info"); setAlertMessage("No file selected."); } }; return ( <div> <> <input type="file" onChange={handleFileChange} onClick={handleFileClick} ref={fileInputRef} // 绑定ref到输入框 /> <button onClick={handleUpload}>Upload</button> <br /> <br /> </> {showAlert && <Alert type={alertType} message={alertMessage} />} </div> ); };
修改说明
- 添加
fileInputRef:通过React ref直接操作文件输入框DOM,上传成功后将其value设为空字符串,强制浏览器重置输入框状态; - 清空文件状态:上传成功后调用
setSelectedFile(null),确保组件状态与输入框DOM状态同步; - 补充缺失状态:原代码中未显示
showAlert等状态定义,需确保组件中已存在这些状态以保证逻辑正常运行。
内容的提问来源于stack exchange,提问作者hkguile
相关产品推荐
相关产品推荐

