ReactJS点击Transfer按钮报preventDefault未定义TypeError问题
问题现象
- React项目中点击Transfer按钮触发TypeError报错,对应业务文件为
transferproduct.js - 控制台错误信息:
transferproduct.js:35 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'preventDefault') - 报错截图:

问题根因
代码存在多处逻辑错误,共同导致报错:
- 事件绑定方式错误:仅给提交按钮绑定
onClick事件,未给<form>标签绑定onSubmit处理逻辑。按钮type="submit"属性会触发浏览器原生表单提交,导致页面刷新,React合成事件对象被回收,后续访问e.preventDefault()时事件对象已为undefined - 事件阻止逻辑位置错误:
handleSubmit函数中先构造提交参数,后调用e.preventDefault(),没有在事件触发第一时间阻止默认提交行为,给页面刷新留了窗口期 - axios响应字段拼写错误:axios封装的响应对象中,接口返回的业务数据存放在
data字段,代码中错误解构为datas,实际拿到的值为undefined,后续执行JSON.parse(datas)会触发二次报错 - 状态读取时机错误:React的
setState是异步执行的,调用setProduct(parseData)后立即读取product.cost时,拿到的还是初始值空数组,不存在cost属性,会触发后续类型错误 - 冗余逻辑和边界缺失:
handleChange中无意义调用e.preventDefault(),localStorage读取产品配置时未做空值兜底,都会埋下额外报错隐患
修复方案
按以下步骤修改代码即可解决问题:
- 将提交事件绑定到
<form>标签的onSubmit属性上,移除按钮上的onClick绑定 - 把
e.preventDefault()放到handleSubmit函数的第一行,事件触发后立即阻止默认表单提交 - 修正axios响应解构的字段名,将错误的
datas改为data - 删除
handleChange中多余的e.preventDefault()调用 - 预算判断逻辑直接使用接口返回的
parseData做判断,不要依赖还未更新的product状态 - 给localStorage读取的配置增加空值兜底,避免取值为null时读取属性报错
修复后的完整代码如下:
import React from 'react'; import { useState } from 'react'; import axios from 'axios'; // 增加空值兜底 const props = JSON.parse(localStorage.getItem('products')) || { budget: 0 }; const TransferProduct = () => { const [product, setProduct] = useState([]); const [data, setData] = useState({ id: '', oname: '', area: '', }); const handleChange = (e) => { // 删除多余的preventDefault调用 const value = e.target.value; setData({ ...data, [e.target.name]: value, }); }; const handleSubmit = async (e) => { // 第一时间阻止默认提交 e.preventDefault(); const userData = { id: data.id, newOwner: data.oname, newArea: data.area, }; try { // 修正axios响应字段名 const { data: resData } = await axios.get( 'http://localhost:8080/api/QueryProductById/' + data.id ); const parseData = JSON.parse(resData); // 直接使用接口返回值做判断,不依赖未更新的state if (parseData.cost < props.budget) { console.log('预算不足,无法完成产品转移'); return; } // 预算校验通过后再发起转移请求 const response = await axios.put( 'http://localhost:8080/api/TransferProduct/' + data.id, userData ); console.log('产品转移成功', response); setProduct(parseData); } catch (error) { if (error.response) { console.log('服务端返回错误:', error.response); } else if (error.request) { console.log('网络异常,请求未发送成功'); } else { console.log('请求配置错误:', error); } } }; return ( <div> {/* 给form绑定提交事件 */} <form onSubmit={handleSubmit}> <label htmlFor='header-search'> <span className='visually-hidden'>From</span> </label> <input type='text' name='id' value={data.id} placeholder='ID' onChange={handleChange} /> <label htmlFor='header-search'> <span className='visually-hidden'>TO</span> </label> <input type='text' name='oname' value={data.oname} placeholder='Enter New Owner' onChange={handleChange} /> <label htmlFor='header-search'> <span className='visually-hidden'>TO</span> </label> <input type='text' name='area' value={data.area} placeholder='Enter new Location' onChange={handleChange} /> <button type='submit'> Transfer </button> </form> </div> ); }; export default TransferProduct;
内容的提问来源于stack exchange,提问作者unknown
相关产品推荐
相关产品推荐

