React中点击表格行时UseEffect频繁触发,求优化方案
解决点击表格行触发不必要更新的优化方案
核心问题
点击表格行初始化地址状态时,useEffect 会因状态变更触发 updateSubmittedApplication,但这只是初始化操作而非用户主动修改,需要区分这两种场景。
方案一:保存初始地址值,对比变化后再更新
新增状态存储初始地址信息,在 useEffect 中对比当前值与初始值,仅当存在实际修改时触发更新。
// 新增初始地址状态 const [initialAddress, setInitialAddress] = useState({}); const rowEvents = { onClick: (e, row) => { toggleTrueFalse(); setModalInfo(row); // 同时保存初始地址和当前地址 const addressData = { AddressLine1: row.AddressLine1, AddressLine2: row.AddressLine2, City: row.City, Province: row.Province, PostalCode: row.Postalcode }; setInitialAddress(addressData); SetAddressLine1(row.AddressLine1); SetAddressLine2(row.AddressLine2); SetCity(row.City); SetProvince(row.Province); SetPostalcode(row.Postalcode); }, }; // 修改useEffect逻辑 useEffect(() => { // 对比当前地址和初始地址是否存在差异 const hasChanged = Object.entries({ AddressLine1: addressLine1, AddressLine2: addressLine2, City: city, Province: province, PostalCode: postalCode }).some(([key, value]) => value !== initialAddress[key]); if (hasChanged) { updateSubmittedApplication(); } }, [addressLine1, addressLine2, city, province, postalCode, initialAddress]);
方案二:移除useEffect,直接利用Editable组件的onSubmit事件
既然Editable组件本身提供了onSubmit回调,可直接将更新逻辑放在此处,完全避免依赖状态变化触发的副作用。
// 移除原有的useEffect // 修改Editable组件的验证和提交逻辑 <Editable editText="Edit" initialValue={addressLine1.toString()} isValueClickable mode="inline" validate={(value) => {if(!value) return '地址不能为空';}} // 修正原验证逻辑的错误 onValidated={(newValue) => {SetAddressLine1(newValue);}} onSubmit={() => { // 仅在用户主动提交编辑时触发更新 updateSubmittedApplication(); }} type="textfield" />
方案三:合并地址状态为单个对象,简化对比逻辑
将分散的地址状态合并为一个对象,既减少状态数量,也更容易对比初始值与当前值:
// 合并地址状态为单个对象 const [address, setAddress] = useState({ AddressLine1: '', AddressLine2: '', City: '', Province: '', PostalCode: '' }); const [initialAddress, setInitialAddress] = useState({}); const rowEvents = { onClick: (e, row) => { toggleTrueFalse(); setModalInfo(row); const addressData = { AddressLine1: row.AddressLine1, AddressLine2: row.AddressLine2, City: row.City, Province: row.Province, PostalCode: row.Postalcode }; setInitialAddress(addressData); setAddress(addressData); }, }; // 修改Editable组件的属性 <Editable editText="Edit" initialValue={address.AddressLine1.toString()} isValueClickable mode="inline" validate={(value) => {if(!value) return '地址不能为空';}} onValidated={(newValue) => { setAddress(prev => ({...prev, AddressLine1: newValue})); }} onSubmit={updateSubmittedApplication} type="textfield" /> // 修改更新函数和useEffect const updateSubmittedApplication = () => { const id = modalInfo.Id; if (Object.values(address).some(val => val)) { axiosPrivate.put(`/updateapp/${id}`, address) .then((res) => { getSubmittedData(); // 修正原状态更新逻辑的错误:用map替换新增操作,避免重复数据 const latestSubmitInfo = submitted.map(item => item.Id === id ? {...item, ...address} : item ); setSubmitted(latestSubmitInfo); console.log(res.data); }); } }; useEffect(() => { // 对比对象是否存在变化 const hasChanged = Object.entries(address).some(([key, val]) => val !== initialAddress[key]); if (hasChanged) { updateSubmittedApplication(); } }, [address, initialAddress]);
额外优化提示
- 原
updateSubmittedApplication中更新submitted状态的逻辑有误,使用map替换[...submitted, updatedSubmit]可避免重复添加数据。 - 原
validate函数逻辑颠倒,应在值为空时返回错误提示,否则不返回内容。
内容的提问来源于stack exchange,提问作者It hurts when IP
相关产品推荐
相关产品推荐

