mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +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 {
|
||||
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]);
|
||||
|
||||
Reference in New Issue
Block a user