From 79aa359c1fe337f2e64cac6ba4d4113976603b48 Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Fri, 28 Nov 2025 21:55:47 +0100 Subject: [PATCH] refactor: lazy load document content only when its tab is active and separate content state reset logic --- frontend/src/documents/DocumentInfoPanel.tsx | 129 ++++++++++++------- 1 file changed, 86 insertions(+), 43 deletions(-) diff --git a/frontend/src/documents/DocumentInfoPanel.tsx b/frontend/src/documents/DocumentInfoPanel.tsx index 21e6257..7d01e64 100644 --- a/frontend/src/documents/DocumentInfoPanel.tsx +++ b/frontend/src/documents/DocumentInfoPanel.tsx @@ -101,50 +101,7 @@ const DocumentInfoPanel: React.FC = ({ return { status: 'idle', data: null, error: null }; }); - useEffect(() => { - if (!contentConfig || !showContentTab) { - setContentState(null); - return undefined; - } - if (!contentEnabled || !loadContent) { - setContentState({ status: contentEnabled ? 'idle' : 'unavailable', data: null, error: null }); - return undefined; - } - - let cancelled = false; - const controller = new AbortController(); - - setContentState({ status: 'loading', data: null, error: null }); - - Promise.resolve(loadContent({ signal: controller.signal })) - .then((result) => { - if (cancelled) { - return; - } - if (result && result.length) { - setContentState({ status: 'loaded', data: result, error: null }); - } else { - setContentState({ status: 'empty', data: '', error: null }); - } - }) - .catch((error) => { - if (cancelled || error?.name === 'AbortError') { - return; - } - setContentState({ - status: 'error', - data: null, - error, - }); - }); - - return () => { - cancelled = true; - controller.abort(); - contentConfig.onCancel?.(); - }; - }, [contentConfig, contentEnabled, showContentTab, document?.id, resetKey, loadContent]); const renderSummarySection = useCallback(() => ( = ({ const activeTabId = isControlled ? controlledActiveTab : uncontrolledTab; + // Track previous ID/key to avoid unnecessary resets on prop reference changes + const prevDocIdRef = React.useRef(document?.id); + const prevResetKeyRef = React.useRef(resetKey); + + // Reset content state when document changes + useEffect(() => { + const docIdChanged = prevDocIdRef.current !== document?.id; + const resetKeyChanged = prevResetKeyRef.current !== resetKey; + + if (docIdChanged || resetKeyChanged) { + prevDocIdRef.current = document?.id; + prevResetKeyRef.current = resetKey; + + if (!contentConfig || !showContentTab) { + setContentState(null); + return; + } + if (!contentEnabled || !loadContent) { + setContentState({ status: contentEnabled ? 'idle' : 'unavailable', data: null, error: null }); + return; + } + // Reset to idle so the loading effect can trigger if needed + setContentState({ status: 'idle', data: null, error: null }); + } + }, [ + contentConfig, + showContentTab, + contentEnabled, + loadContent, + document?.id, + resetKey, + ]); + + // Lazy load content when tab is active + useEffect(() => { + const contentTabId = contentConfig?.id || 'content'; + const isActive = activeTabId === contentTabId; + + if (!isActive || !contentConfig || !loadContent || !contentEnabled) { + return undefined; + } + + if (contentState?.status !== 'idle') { + return undefined; + } + + let cancelled = false; + const controller = new AbortController(); + + setContentState({ status: 'loading', data: null, error: null }); + + Promise.resolve(loadContent({ signal: controller.signal })) + .then((result) => { + if (cancelled) { + return; + } + if (result && result.length) { + setContentState({ status: 'loaded', data: result, error: null }); + } else { + setContentState({ status: 'empty', data: '', error: null }); + } + }) + .catch((error) => { + if (cancelled || error?.name === 'AbortError') { + return; + } + setContentState({ + status: 'error', + data: null, + error, + }); + }); + + return () => { + cancelled = true; + controller.abort(); + contentConfig.onCancel?.(); + }; + }, [ + activeTabId, + contentConfig, + loadContent, + contentEnabled, + contentState?.status, + ]); + const handleTabSelect = (tabId) => { if (!visibleTabs.some((tab) => tab.id === tabId)) { return;