From 5e40dbbcd2cd0768258d15fb742cf25e19b6f38b Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 15 Mar 2026 11:32:13 +0000 Subject: [PATCH] fix: reliably init grid width on page refresh using useLayoutEffect useResizeObserver reads ref.current at render time; on page refresh with fast SWR cache, no re-render occurs after mount so ref.current remains null in the effect, observation never starts, and containerWidth stays 0 forever. Add a useLayoutEffect that measures offsetWidth synchronously before paint as a seed value (effectiveWidth = containerWidth || initialWidth). Once ResizeObserver fires normally, containerWidth takes over. The Responsive grid is gated on effectiveWidth > 0 so it always renders correctly on both first load and refresh. https://claude.ai/code/session_01H1sqbcFmtwwsdNTJcJHJWd --- web/src/views/live/DraggableGridLayout.tsx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/web/src/views/live/DraggableGridLayout.tsx b/web/src/views/live/DraggableGridLayout.tsx index 1f75c2fc4..c35bacbf3 100644 --- a/web/src/views/live/DraggableGridLayout.tsx +++ b/web/src/views/live/DraggableGridLayout.tsx @@ -332,6 +332,20 @@ export default function DraggableGridLayout({ const [{ width: containerWidth, height: containerHeight }] = useResizeObserver(gridContainerRef); + // useResizeObserver reads ref.current at render time, so it may miss the + // initial mount when ref.current is null (e.g. on page refresh with cached + // SWR data). Measure the container synchronously in useLayoutEffect as a + // reliable seed value; containerWidth from ResizeObserver takes over once + // it fires. + const [initialWidth, setInitialWidth] = useState(0); + useLayoutEffect(() => { + if (gridContainerRef.current) { + setInitialWidth(gridContainerRef.current.offsetWidth); + } + }, []); + + const effectiveWidth = containerWidth || initialWidth; + const scrollBarWidth = useMemo(() => { if (containerWidth && containerHeight && containerRef.current) { return ( @@ -342,8 +356,8 @@ export default function DraggableGridLayout({ }, [containerRef, containerHeight, containerWidth]); const availableWidth = useMemo( - () => (scrollBarWidth ? containerWidth + scrollBarWidth : containerWidth), - [containerWidth, scrollBarWidth], + () => (scrollBarWidth ? effectiveWidth + scrollBarWidth : effectiveWidth), + [effectiveWidth, scrollBarWidth], ); const hasScrollbar = useMemo(() => { @@ -710,7 +724,7 @@ export default function DraggableGridLayout({ currentGroups={groups} activeGroup={group} /> - {containerWidth > 0 && 0 &&