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