Next.js中使用onChange事件处理文件上传时出现DOMException错误的排查与解决
嘿,我来帮你分析这个问题!你遇到的Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable错误,其实是两个关键问题导致的,咱们一步步拆解:
问题根源分析
File Input的value属性是只读的
你在GenericForm组件里给所有类型的input都传递了value属性,包括file类型的input。但浏览器出于安全限制,file input的value是只读的——你只能清空它(设为空字符串),不能手动设置成其他值,更不能把File对象直接塞进去。当你尝试给file input赋值formData[field.name](也就是选中的File对象)时,浏览器就会抛出这个DOM异常。React State中存储File对象的风险
即使避开了value的问题,把File对象直接存在React state里也不安全。File对象和浏览器的DOM上下文绑定,当组件重新渲染时,这个对象可能会失去有效性,导致后续操作报错。
针对性解决方案
咱们只需要修改两处关键代码就能解决问题:
1. 给File类型Input移除value属性
在GenericForm组件渲染FormGroup的时候,判断如果是file类型的输入,就不要传递value属性:
<FormGroup label={field.label} inputType={field.inputType} inputProps={{ // 仅非file类型的input才传递value属性 ...(field.inputType !== "file" && { value: formData[field.name] || "" }), onChange: combinedHandleChange, name: field.name, }} selectOptions={field.selectOptions} error={errors[field.name]} />
2. 避免在FormData State中存储File对象
修改GenericForm里的combinedHandleChange函数,当处理file类型的输入时,不要把File对象存入formData(因为你已经在TrabajaConNosotros组件里用selectedFile单独处理文件了):
const combinedHandleChange = (event: React.ChangeEvent<HTMLInputElement>) => { if (handleChange) { handleChange(event); } const { name, value, files } = event.target as HTMLInputElement & { files: FileList | null; }; // 对于file类型输入,不将File对象存入formData(由子组件单独处理) if (files) { return; } setFormData((prevData) => ({ ...prevData, [name]: value, })); };
为什么这样修改有效?
- 第一处修改解决了“试图修改只读属性”的核心DOM错误,符合浏览器对File input的安全限制;
- 第二处修改避免了在state中存储可能失效的File对象,让文件处理逻辑完全由
TrabajaConNosotros里的selectedFile来管理,更安全可靠。
做完这两处修改后,你再测试文件上传功能,那个DOMException应该就消失了,表单也能正常提交带文件的数据啦!
备注:内容来源于stack exchange,提问作者mateo ghidini

