From fbb0dd7b32b523677d0d88ce2856a1ea1cfde74e Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sat, 23 Aug 2025 11:21:37 +0100 Subject: [PATCH] Bugfix: Fixed object update and creation ws. --- .../Dashboard/common/ObjectTable.jsx | 55 ++++++++++++++----- .../Dashboard/context/ApiServerContext.jsx | 10 ++-- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/components/Dashboard/common/ObjectTable.jsx b/src/components/Dashboard/common/ObjectTable.jsx index 34eab30..84d4896 100644 --- a/src/components/Dashboard/common/ObjectTable.jsx +++ b/src/components/Dashboard/common/ObjectTable.jsx @@ -82,10 +82,14 @@ const ObjectTable = forwardRef( // Table state const [pages, setPages] = useState([]) + const pagesRef = useRef(pages) const [hasMore, setHasMore] = useState(true) const [loading, setLoading] = useState(true) const [lazyLoading, setLazyLoading] = useState(false) + const [subscribedIds, setSubscribedIds] = useState([]) + const [typeSubscribed, setTypeSubscribed] = useState(false) + const rowActions = model.actions?.filter((action) => action.row == true) || [] @@ -140,6 +144,7 @@ const ObjectTable = forwardRef( order: sorter.order }) } + console.log('Fetching data...') try { const result = await fetchObjects(type, { page: pageNum, @@ -273,25 +278,27 @@ const ObjectTable = forwardRef( const reload = useCallback(async () => { setLazyLoading(true) - for (let i = 0; i < pages.length; i++) { - const page = pages[i] + console.log('Pages during reload', pagesRef.current) + for (let i = 0; i < pagesRef.current.length; i++) { + const page = pagesRef.current[i] await fetchData(page.pageNum) } - }, [fetchData, pages]) + }, [fetchData]) // Update event handler for real-time updates - const updateEventHandler = useCallback((updatedData) => { + const updateEventHandler = useCallback((id, updatedData) => { setPages((prevPages) => prevPages.map((page) => ({ ...page, - items: page.items.map((item) => - item._id === updatedData._id ? merge({}, item, updatedData) : item - ) + items: page.items.map((item) => { + return item._id === id ? merge({}, item, updatedData) : item + }) })) ) }, []) const newEventHandler = useCallback(() => { + console.log('GOT NEW EVENT') reload() }, [reload]) @@ -299,17 +306,19 @@ const ObjectTable = forwardRef( useEffect(() => { if (pages.length > 0 && connected) { const unsubscribes = [] - // Subscribe to each item in all pages pages.forEach((page) => { if (page?.items && page?.items?.length > 0) { page.items.forEach((item) => { - if (!item.isSkeleton) { + if (!item.isSkeleton && !subscribedIds.includes(item?._id)) { const unsubscribe = subscribeToObjectUpdates( item._id, type, - updateEventHandler + (updateData) => { + updateEventHandler(item._id, updateData) + } ) + setSubscribedIds((prev) => [...prev, item._id]) if (unsubscribe) { unsubscribes.push(unsubscribe) } @@ -325,18 +334,32 @@ const ObjectTable = forwardRef( }) } } - }, [pages, type, subscribeToObjectUpdates, updateEventHandler, connected]) + }, [ + pages, + type, + subscribeToObjectUpdates, + updateEventHandler, + connected, + subscribedIds + ]) useEffect(() => { - if (connected == true) { + if (connected == true && typeSubscribed == false) { const unsubscribe = subscribeToObjectTypeUpdates(type, newEventHandler) + setTypeSubscribed(true) return () => { - if (unsubscribe) { + if (unsubscribe && typeSubscribed == true) { unsubscribe() } } } - }, [type, subscribeToObjectTypeUpdates, connected, newEventHandler]) + }, [ + type, + subscribeToObjectTypeUpdates, + connected, + newEventHandler, + typeSubscribed + ]) const updateData = useCallback( (_id, updatedData) => { @@ -451,6 +474,10 @@ const ObjectTable = forwardRef( } ] + useEffect(() => { + console.log('Pages', pages) + pagesRef.current = pages + }, [pages]) // Add columns in the order specified by model.columns model.columns.forEach((colName) => { const prop = modelProperties.find((p) => p.name === colName) diff --git a/src/components/Dashboard/context/ApiServerContext.jsx b/src/components/Dashboard/context/ApiServerContext.jsx index 0776338..1009cfb 100644 --- a/src/components/Dashboard/context/ApiServerContext.jsx +++ b/src/components/Dashboard/context/ApiServerContext.jsx @@ -243,16 +243,17 @@ const ApiServerProvider = ({ children }) => { const offObjectUpdatesEvent = useCallback((id, objectType, callback) => { if (socketRef.current && socketRef.current.connected == true) { + const callbacksRefKey = `${objectType}:${id}` // Remove callback from the subscribed callbacks map - if (subscribedCallbacksRef.current.has(id)) { + if (subscribedCallbacksRef.current.has(callbacksRefKey)) { const callbacks = subscribedCallbacksRef.current - .get(id) + .get(callbacksRefKey) .filter((cb) => cb !== callback) if (callbacks.length === 0) { - subscribedCallbacksRef.current.delete(id) + subscribedCallbacksRef.current.delete(callbacksRefKey) socketRef.current.emit('unsubscribe', { id: id, type: objectType }) } else { - subscribedCallbacksRef.current.set(id, callbacks) + subscribedCallbacksRef.current.set(callbacksRefKey, callbacks) } } } @@ -261,6 +262,7 @@ const ApiServerProvider = ({ children }) => { const offObjectTypeUpdatesEvent = useCallback((objectType, callback) => { if (socketRef.current && socketRef.current.connected == true) { // Remove callback from the subscribed callbacks map + console.log('Unsubscribing from type') if (subscribedCallbacksRef.current.has(objectType)) { const callbacks = subscribedCallbacksRef.current .get(objectType)