Refactor ObjectForm to enhance state management and activity handling
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Introduced a ref to track fetched objects, improving fetch logic clarity and preventing unnecessary updates.
- Updated event handlers for object updates and activity subscriptions to ensure they only trigger for the current object, enhancing performance and reducing potential errors.
- Consolidated state updates and notifications within useEffect hooks for better organization and efficiency.
This commit is contained in:
Tom Butcher 2026-07-26 01:58:35 +01:00
parent 78dba97107
commit ff61cd4f06

View File

@ -197,6 +197,7 @@ const ObjectForm = forwardRef(
// Update refs when values change
useEffect(() => {
onStateChangeRef.current = onStateChange
currentIdRef.current = id
currentTypeRef.current = type
currentIsEditingRef.current = isEditing
@ -416,11 +417,18 @@ const ObjectForm = forwardRef(
}, []) // Empty dependency array - only run on mount/unmount
const handleFetchObject = useCallback(async () => {
const objectKey = `${type}:${id}`
try {
setFetchLoading(true)
onStateChangeRef.current({ loading: true })
const data = await fetchObject(id, type)
const initialActivities = await fetchObjectActivities(id, type)
if (fetchedObjectRef.current !== objectKey) {
return
}
setActivities(initialActivities)
if (
@ -469,23 +477,10 @@ const ObjectForm = forwardRef(
)
}, [])
// Update event handler
const updateActivityEventHandler = useCallback((activity, activitiesList) => {
setActivities((prev) => {
return Array.isArray(activitiesList)
? activitiesList
: applyActivityUpdate(prev, activity)
})
}, [])
useEffect(() => {
if (!id) {
return
}
notifyActivityState(activities)
handleEditingConflict(activities)
}, [activities, id, notifyActivityState, handleEditingConflict])
}, [activities, notifyActivityState, handleEditingConflict])
useEffect(() => {
if (connected !== true || !id || token == null) {
@ -497,29 +492,60 @@ const ObjectForm = forwardRef(
return
}
const previousObjectKey = fetchedObjectRef.current
if (previousObjectKey) {
const colonIndex = previousObjectKey.indexOf(':')
const previousType = previousObjectKey.slice(0, colonIndex)
const previousId = previousObjectKey.slice(colonIndex + 1)
clearObjectActivity(previousId, previousType)
}
fetchedObjectRef.current = objectKey
setIsEditing(false)
isEditingRef.current = false
setActivities([])
notifyActivityState([])
form.resetFields()
handleFetchObject()
}, [id, type, token, connected, handleFetchObject, form])
}, [
id,
type,
token,
connected,
handleFetchObject,
form,
notifyActivityState,
clearObjectActivity
])
useEffect(() => {
if (!id) {
return
}
const objectKey = `${type}:${id}`
const activityHandler = (activity, activitiesList) => {
if (fetchedObjectRef.current !== objectKey) {
return
}
setActivities((prev) => {
return Array.isArray(activitiesList)
? activitiesList
: applyActivityUpdate(prev, activity)
})
}
const activityUnsubscribe = subscribeToObjectActivity(
id,
type,
updateActivityEventHandler
activityHandler
)
return () => {
if (activityUnsubscribe) activityUnsubscribe()
}
}, [id, type, subscribeToObjectActivity, updateActivityEventHandler])
}, [id, type, subscribeToObjectActivity])
useEffect(() => {
if (id && connected == true) {
@ -529,10 +555,19 @@ const ObjectForm = forwardRef(
isEditingRef.current == true ? 'editing' : 'viewing'
)
const objectKey = `${type}:${id}`
const objectUpdateHandler = (value) => {
if (fetchedObjectRef.current !== objectKey) {
return
}
updateObjectEventHandler(value)
}
const objectUpdatesUnsubscribe = subscribeToObjectUpdates(
id,
type,
updateObjectEventHandler
objectUpdateHandler
)
return () => {