fix: prevent cmd-k scroll reset on catalog poll refresh
All checks were successful
CI / build (push) Successful in 1m49s
CI / cleanup-branch (push) Has been skipped
CI / docker (push) Successful in 2m3s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 1m0s

The searchData useMemo recomputed on every catalog poll cycle because
catalogData got a new array reference even when content was unchanged.
This caused the CommandPalette list to re-render and reset scroll.

Use a ref with deep equality check to keep a stable catalog reference,
only updating when the actual data changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-01 21:22:50 +02:00
parent 910230cbf8
commit b30a5b5760

View File

@@ -5,7 +5,7 @@ import { useRouteCatalog } from '../api/queries/catalog';
import { useAgents } from '../api/queries/agents';
import { useSearchExecutions } from '../api/queries/executions';
import { useAuthStore } from '../auth/auth-store';
import { useState, useMemo, useCallback, useEffect } from 'react';
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
import { ContentTabs } from './ContentTabs';
import { useScope } from '../hooks/useScope';
@@ -145,6 +145,13 @@ function LayoutContent() {
[catalog, agents],
);
// Stable reference for catalog data — only changes when catalog/agents actually change,
// not on every poll cycle (prevents cmd-k scroll reset)
const catalogRef = useRef(catalogData);
if (catalogData !== catalogRef.current && JSON.stringify(catalogData) !== JSON.stringify(catalogRef.current)) {
catalogRef.current = catalogData;
}
const searchData: SearchResult[] = useMemo(() => {
const exchangeItems: SearchResult[] = (exchangeResults?.data || []).map((e: any) => ({
id: e.executionId,
@@ -178,8 +185,8 @@ function LayoutContent() {
}
}
return [...catalogData, ...exchangeItems, ...attributeItems];
}, [catalogData, exchangeResults, debouncedQuery]);
return [...catalogRef.current, ...exchangeItems, ...attributeItems];
}, [catalogRef.current, exchangeResults, debouncedQuery]);
const isAdminPage = location.pathname.startsWith('/admin');
const breadcrumb = useMemo(() => {