Fix catalog filter flicker caused by stale render cycle

The EntityListProvider exposed entities from `outputState` (synced via
useEffect) but `loading` from `useAsyncFn`. When the async function
resolved, `loading` flipped to false one render before `outputState`
updated, causing a flash of stale data between the loading indicator
and the new results.

Use `resolvedValue` directly in the context value when available,
eliminating the extra render lag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
This commit is contained in:
Fredrik Adelöw
2026-03-19 09:49:05 +01:00
parent e9306006f6
commit 51aacae34b
2 changed files with 19 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
Fixed a UI flicker in the catalog entity list where changing a filter would briefly flash stale data before showing the new results.
@@ -454,30 +454,36 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(
[paginationMode],
);
// Use resolvedValue directly when available to avoid an extra render cycle.
// Without this, there's a render where loading has flipped back to false but
// outputState hasn't been updated yet (it syncs via useEffect), causing a
// flash of stale data between the loading state and the new results.
const latestOutput = resolvedValue ?? outputState;
const pageInfo = useMemo(() => {
if (paginationMode !== 'cursor') {
return undefined;
}
const prevCursor = outputState.pageInfo?.prevCursor;
const nextCursor = outputState.pageInfo?.nextCursor;
const prevCursor = latestOutput.pageInfo?.prevCursor;
const nextCursor = latestOutput.pageInfo?.nextCursor;
return {
prev: prevCursor ? () => setCursor(prevCursor) : undefined,
next: nextCursor ? () => setCursor(nextCursor) : undefined,
};
}, [paginationMode, outputState.pageInfo]);
}, [paginationMode, latestOutput.pageInfo]);
const value = useMemo(
() => ({
filters: outputState.appliedFilters,
entities: outputState.entities,
backendEntities: outputState.backendEntities,
filters: latestOutput.appliedFilters,
entities: latestOutput.entities,
backendEntities: latestOutput.backendEntities,
updateFilters,
queryParameters,
loading,
error,
pageInfo,
totalItems: outputState.totalItems,
totalItems: latestOutput.totalItems,
limit,
offset,
setLimit,
@@ -485,7 +491,7 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(
paginationMode,
}),
[
outputState,
latestOutput,
updateFilters,
queryParameters,
loading,