Refactor ObjectForm component to improve computed value handling

- Introduced a working copy of currentData to facilitate sequential updates of computed values.
- Updated property processing logic to utilize workingData for accurate calculations.
- Removed unnecessary parameters in processProperty function for cleaner code.
- Enhanced dependency array in useEffect to include calculateComputedValues and model for better reactivity.
This commit is contained in:
Tom Butcher 2025-12-07 02:41:55 +00:00
parent 6da485bc8f
commit b955f42b88

View File

@ -134,6 +134,10 @@ const ObjectForm = forwardRef(
return []
}
// Clone currentData to allow sequential updates
// We use this working copy to calculate subsequent dependent values
const workingData = merge({}, currentData)
const normalizedPath = (name, parentPath = []) => {
if (Array.isArray(name)) {
return [...parentPath, ...name]
@ -159,11 +163,17 @@ const ObjectForm = forwardRef(
const computedEntries = []
const processProperty = (property, scopeData, parentPath = []) => {
const processProperty = (property, parentPath = []) => {
if (!property?.name) return
const propertyPath = normalizedPath(property.name, parentPath)
// Determine the scope data for calculation (parent object)
const scopeData =
parentPath.length === 0
? workingData
: getValueAtPath(workingData, parentPath)
if (property.value && typeof property.value === 'function') {
try {
const computedValue = property.value(scopeData || {})
@ -172,6 +182,8 @@ const ObjectForm = forwardRef(
namePath: propertyPath,
value: computedValue
})
// Update workingData so subsequent properties can use this value
set(workingData, propertyPath, computedValue)
}
} catch (error) {
console.warn(
@ -186,29 +198,25 @@ const ObjectForm = forwardRef(
property.properties.length > 0
) {
if (property.type === 'objectChildren') {
const childValues = getValueAtPath(currentData, propertyPath)
// Use workingData to get the latest state of children
const childValues = getValueAtPath(workingData, propertyPath)
if (Array.isArray(childValues)) {
childValues.forEach((childData = {}, index) => {
childValues.forEach((_, index) => {
property.properties.forEach((childProperty) => {
processProperty(childProperty, childData || {}, [
...propertyPath,
index
])
processProperty(childProperty, [...propertyPath, index])
})
})
}
} else {
const nestedScope =
getValueAtPath(currentData, propertyPath) || {}
property.properties.forEach((childProperty) => {
processProperty(childProperty, nestedScope || {}, propertyPath)
processProperty(childProperty, propertyPath)
})
}
}
}
modelDefinition.properties.forEach((property) => {
processProperty(property, currentData)
processProperty(property, [])
})
return computedEntries
@ -294,7 +302,17 @@ const ObjectForm = forwardRef(
fetchObject
)
}
}, [fetchObject, fetchObjectLock, id, type, form, messageApi, showError])
}, [
fetchObject,
fetchObjectLock,
id,
type,
form,
messageApi,
showError,
calculateComputedValues,
model
])
// Update event handler
const updateObjectEventHandler = useCallback((value) => {
@ -354,7 +372,6 @@ const ObjectForm = forwardRef(
const startEditing = () => {
setIsEditing(true)
isEditingRef.current = true
console.log('IS EDITING TRUE')
setObjectData((prev) => ({ ...prev, _isEditing: isEditingRef.current }))
onStateChangeRef.current({
isEditing: true,
@ -379,7 +396,6 @@ const ObjectForm = forwardRef(
setIsEditing(false)
isEditingRef.current = false
form.setFieldsValue(resetFormData)
console.log('IS EDITING FALSE')
setObjectData({ ...resetFormData, _isEditing: isEditingRef.current })
}
@ -486,7 +502,7 @@ const ObjectForm = forwardRef(
// Calculate computed values based on current form data
const currentFormData = {
...(serverObjectData.current || {}),
...allFormValues
...changedValues
}
const computedEntries = calculateComputedValues(
currentFormData,
@ -519,7 +535,7 @@ const ObjectForm = forwardRef(
mergedFormValues._isEditing = isEditingRef.current
setObjectData((prev) => {
return { ...prev, ...mergedFormValues }
return merge({}, prev, mergedFormValues)
})
}}
>