mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
retry autofit calculation to prevent zero value on initial render and memoization
This commit is contained in:
+53
-9
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect } from 'react';
|
import { useLayoutEffect } from 'react';
|
||||||
|
|
||||||
interface UseContainerWidthTrackingProps {
|
interface UseContainerWidthTrackingProps {
|
||||||
autoFitColumns: boolean;
|
autoFitColumns: boolean;
|
||||||
@@ -18,14 +18,58 @@ export const useContainerWidthTracking = ({
|
|||||||
setCenterContainerWidth,
|
setCenterContainerWidth,
|
||||||
setTotalContainerWidth,
|
setTotalContainerWidth,
|
||||||
}: UseContainerWidthTrackingProps) => {
|
}: 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)
|
// Track center container width (for column distribution)
|
||||||
useEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const el = rowRef.current;
|
const el = rowRef.current;
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
|
||||||
const updateWidth = () => {
|
const { cancel, updateWidth } = createWidthUpdater(el, setCenterContainerWidth);
|
||||||
setCenterContainerWidth(el.clientWidth || 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
updateWidth();
|
updateWidth();
|
||||||
|
|
||||||
@@ -45,18 +89,17 @@ export const useContainerWidthTracking = ({
|
|||||||
if (debounceTimeout) {
|
if (debounceTimeout) {
|
||||||
clearTimeout(debounceTimeout);
|
clearTimeout(debounceTimeout);
|
||||||
}
|
}
|
||||||
|
cancel();
|
||||||
resizeObserver.disconnect();
|
resizeObserver.disconnect();
|
||||||
};
|
};
|
||||||
}, [rowRef, setCenterContainerWidth]);
|
}, [rowRef, setCenterContainerWidth]);
|
||||||
|
|
||||||
// Track total container width for autoFitColumns
|
// Track total container width for autoFitColumns
|
||||||
useEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const el = containerRef.current;
|
const el = containerRef.current;
|
||||||
if (!el || !autoFitColumns) return;
|
if (!el || !autoFitColumns) return;
|
||||||
|
|
||||||
const updateWidth = () => {
|
const { cancel, updateWidth } = createWidthUpdater(el, setTotalContainerWidth);
|
||||||
setTotalContainerWidth(el.clientWidth || 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
updateWidth();
|
updateWidth();
|
||||||
|
|
||||||
@@ -76,6 +119,7 @@ export const useContainerWidthTracking = ({
|
|||||||
if (debounceTimeout) {
|
if (debounceTimeout) {
|
||||||
clearTimeout(debounceTimeout);
|
clearTimeout(debounceTimeout);
|
||||||
}
|
}
|
||||||
|
cancel();
|
||||||
resizeObserver.disconnect();
|
resizeObserver.disconnect();
|
||||||
};
|
};
|
||||||
}, [autoFitColumns, containerRef, setTotalContainerWidth]);
|
}, [autoFitColumns, containerRef, setTotalContainerWidth]);
|
||||||
|
|||||||
Reference in New Issue
Block a user