diff --git a/docker/frontend/src/Library.tsx b/docker/frontend/src/Library.tsx index dd083a0..45101d5 100644 --- a/docker/frontend/src/Library.tsx +++ b/docker/frontend/src/Library.tsx @@ -2937,6 +2937,13 @@ function useWallWindow(count: number, on: boolean): { ref: RefObject(null); // The first window is a screenful: the wall has not been measured yet. const [win, setWin] = useState(() => ({ from: 0, to: Math.min(count, 24), above: 0, below: 0 })); + // The window last written, because the reader of a `setWin` in a layout effect + // is not the state: a set made from a layout effect renders again whether or + // not the value moved, and this one is remeasured after every render — so a set + // it did not need is the screen's own render loop (React #185, "Maximum update + // depth exceeded"). The ref is the guard: nothing is set that the wall already + // stands at. + const winRef = useRef(win); const measureRef = useRef<() => void>(() => {}); // The window over a scroll container is taken rather than kept, so it is taken // after every render: the first pass draws a screenful, the next reads the row's @@ -2947,6 +2954,15 @@ function useWallWindow(count: number, on: boolean): { ref: RefObject { + const prev = winRef.current; + if (prev.from === next.from && prev.to === next.to && prev.above === next.above && prev.below === next.below) return; + winRef.current = next; + setWin(next); + }; const measure = () => { const cards = el.querySelectorAll(':scope > .adm-card'); const first = cards[0]; @@ -2956,7 +2972,7 @@ function useWallWindow(count: number, on: boolean): { ref: RefObject (prev.from === 0 && prev.to === to && !prev.above && !prev.below ? prev : { from: 0, to, above: 0, below: 0 })); + show({ from: 0, to, above: 0, below: 0 }); return; } // The step from one row to the next, taken as the drawn run's own average. @@ -2978,9 +2994,7 @@ function useWallWindow(count: number, on: boolean): { ref: RefObject - prev.from === from && prev.to === to && prev.above === above && prev.below === below ? prev : { from, to, above, below } - ); + show({ from, to, above, below }); }; measureRef.current = measure; const onScroll = () => measure();