From b45594515e62f91e774ef747a138f2de1aab407c Mon Sep 17 00:00:00 2001 From: jeffvli Date: Thu, 22 Jan 2026 02:53:25 -0800 Subject: [PATCH] retry autofit calculation to prevent zero value on initial render and memoization --- .../hooks/use-container-width-tracking.ts | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/renderer/components/item-list/item-table-list/hooks/use-container-width-tracking.ts b/src/renderer/components/item-list/item-table-list/hooks/use-container-width-tracking.ts index fc2415d26..d3c77a293 100644 --- a/src/renderer/components/item-list/item-table-list/hooks/use-container-width-tracking.ts +++ b/src/renderer/components/item-list/item-table-list/hooks/use-container-width-tracking.ts @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useLayoutEffect } from 'react'; interface UseContainerWidthTrackingProps { autoFitColumns: boolean; @@ -18,14 +18,58 @@ export const useContainerWidthTracking = ({ setCenterContainerWidth, setTotalContainerWidth, }: UseContainerWidthTrackingProps) => { + const createWidthUpdater = ( + el: HTMLDivElement, + setWidth: (width: number) => void, + opts?: { maxRafRetries?: number }, + ) => { + const maxRafRetries = opts?.maxRafRetries ?? 10; + let rafId: null | number = null; + + const cancel = () => { + if (rafId !== null) cancelAnimationFrame(rafId); + rafId = null; + }; + + const updateWidth = () => { + const measured = el.clientWidth || 0; + if (measured > 0) { + cancel(); + setWidth(measured); + return; + } + + // Some layouts can report 0 on first paint + // Retry a few frames to catch the first non-zero measurement + cancel(); + let attempts = 0; + const retry = () => { + const next = el.clientWidth || 0; + if (next > 0) { + rafId = null; + setWidth(next); + return; + } + attempts++; + if (attempts < maxRafRetries) { + rafId = requestAnimationFrame(retry); + } else { + rafId = null; + setWidth(0); + } + }; + rafId = requestAnimationFrame(retry); + }; + + return { cancel, updateWidth }; + }; + // Track center container width (for column distribution) - useEffect(() => { + useLayoutEffect(() => { const el = rowRef.current; if (!el) return; - const updateWidth = () => { - setCenterContainerWidth(el.clientWidth || 0); - }; + const { cancel, updateWidth } = createWidthUpdater(el, setCenterContainerWidth); updateWidth(); @@ -45,18 +89,17 @@ export const useContainerWidthTracking = ({ if (debounceTimeout) { clearTimeout(debounceTimeout); } + cancel(); resizeObserver.disconnect(); }; }, [rowRef, setCenterContainerWidth]); // Track total container width for autoFitColumns - useEffect(() => { + useLayoutEffect(() => { const el = containerRef.current; if (!el || !autoFitColumns) return; - const updateWidth = () => { - setTotalContainerWidth(el.clientWidth || 0); - }; + const { cancel, updateWidth } = createWidthUpdater(el, setTotalContainerWidth); updateWidth(); @@ -76,6 +119,7 @@ export const useContainerWidthTracking = ({ if (debounceTimeout) { clearTimeout(debounceTimeout); } + cancel(); resizeObserver.disconnect(); }; }, [autoFitColumns, containerRef, setTotalContainerWidth]);