Refactor ObjectForm component to implement debounced validation and state updates, improving performance and reducing unnecessary re-renders.

This commit is contained in:
Tom Butcher 2025-11-24 03:31:51 +00:00
parent 6af832afe5
commit e788eaba91

View File

@ -138,8 +138,9 @@ const ObjectForm = forwardRef(
return computedValues
}, [])
// Validate form on change
// Validate form on change (debounced to avoid heavy work on every keystroke)
useEffect(() => {
const timeoutId = setTimeout(() => {
form
.validateFields({ validateOnly: true })
.then(() => {
@ -150,12 +151,16 @@ const ObjectForm = forwardRef(
})
})
.catch(() => {
setFormValid(false)
onStateChange({
formValid: true,
formValid: false,
objectData: { ...serverObjectData, ...form.getFieldsValue() }
})
})
}, [form, formUpdateValues])
}, 150)
return () => clearTimeout(timeoutId)
}, [form, formUpdateValues, onStateChange, serverObjectData])
// Cleanup on unmount
useEffect(() => {
@ -252,9 +257,14 @@ const ObjectForm = forwardRef(
updateLockEventHandler
])
// Debounce objectData updates sent to parent to limit re-renders
useEffect(() => {
const timeoutId = setTimeout(() => {
onStateChange({ objectData })
}, [objectData])
}, 150)
return () => clearTimeout(timeoutId)
}, [objectData, onStateChange])
const startEditing = () => {
setIsEditing(true)
@ -366,10 +376,19 @@ const ObjectForm = forwardRef(
model
)
// Update form with computed values if any were calculated
// Update form with computed values if any were calculated and they changed
if (Object.keys(computedValues).length > 0) {
const currentComputedValues = form.getFieldsValue(
Object.keys(computedValues)
)
const hasDiff = Object.keys(computedValues).some(
(key) => currentComputedValues[key] !== computedValues[key]
)
if (hasDiff) {
form.setFieldsValue(computedValues)
}
}
// Merge all values (user input + computed values)
const allValues = { ...values, ...computedValues }