使用自定义输入Hook清空React表单时遇报错,求解决方法
React表单提交后无法清空的问题解决
问题根源
你自定义的useFormFields Hook返回的第二个参数是处理输入变化的事件回调函数,并非直接更新state的setValues方法。当你在handleSubmit里调用setFormData(data)时,data会被当成event传入回调函数,而普通对象没有target属性,所以会抛出Cannot destructure property 'target' of 'event' as it is undefined的错误。
另外,你当前的输入框没有绑定value属性,属于非受控组件,即使state被重置,输入框的显示内容也不会同步更新,这也是表单无法清空的隐性问题。
解决方案一:给Hook添加重置方法
修改useFormFields,新增一个专门的重置函数并返回:
export function useFormFields(initialState) { const [fields, setValues] = useState(initialState); // 新增重置表单的函数 const resetFields = () => { setValues(initialState); }; return [ fields, function(event) { try { const { name, value, type, checked } = event.target; setValues({ ...fields, [name]: type === "checkbox" ? checked : value, }); } catch (err) { console.log(err); } }, resetFields // 返回重置函数 ]; }
在组件中调用并使用重置函数,同时给输入框绑定value:
function NewMachine() { const initialData = { user_level:"", name: "", email: "", }; // 解构出重置函数 const [formData, setFormData, resetForm] = useFormFields(initialData); const handleSubmit = (e) => { e.preventDefault(); console.log(formData); resetForm(); // 调用重置函数清空表单 }; return ( <div> <form onSubmit={handleSubmit} autoComplete="off"> <input placeholder="Enter Name" className="form-control" id="name" name="name" onChange={setFormData} value={formData.name} // 绑定value,让输入框成为受控组件 required /> {/* 其他字段也要同步绑定对应的value */} <button className="float-right btn btn-secondary" type="submit"> Create New User </button> </form> </div> ); }
解决方案二:兼容事件和对象输入的回调函数
如果不想新增重置函数,可以修改Hook里的回调,让它既能处理事件,也能直接接收对象更新state:
export function useFormFields(initialState) { const [fields, setValues] = useState(initialState); return [ fields, function(input) { // 判断传入的是事件对象还是普通更新对象 if (input.target) { try { const { name, value, type, checked } = input.target; setValues({ ...fields, [name]: type === "checkbox" ? checked : value, }); } catch (err) { console.log(err); } } else { // 传入对象时直接更新state setValues(input); } }, ]; }
组件中直接调用setFormData传入初始对象,同时绑定输入框的value:
function NewMachine() { const initialData = { user_level:"", name: "", email: "", }; const [formData, setFormData] = useFormFields(initialData); const handleSubmit = (e) => { e.preventDefault(); console.log(formData); setFormData(initialData); // 直接传入初始对象重置表单 }; return ( <div> <form onSubmit={handleSubmit} autoComplete="off"> <input placeholder="Enter Name" className="form-control" id="name" name="name" onChange={setFormData} value={formData.name} // 绑定value同步显示 required /> {/* 其他字段同理绑定value */} <button className="float-right btn btn-secondary" type="submit"> Create New User </button> </form> </div> ); }
内容的提问来源于stack exchange,提问作者Denis Morgan
相关产品推荐
相关产品推荐

