fix: add workaround for gutter to update vertical gap#48
Conversation
🦋 Changeset detectedLatest commit: 001a15a The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds a workaround in ChangesGutter Remeasure Workaround
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Component
participant useMasonry
participant Virtualizer
Component->>useMasonry: render with new gutter prop
useMasonry->>useMasonry: compare gutter to prevGutter ref
alt gutter changed
useMasonry->>useMasonry: update prevGutter ref
useMasonry->>Virtualizer: measure()
else gutter unchanged
useMasonry-->>Component: no remeasure triggered
end
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
package/src/hooks/useMasonry.ts (1)
128-136: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winUse
useLayoutEffectto avoid a visible flash of stale spacing.
virtualizer.measure()runs in a passiveuseEffect, which fires after the browser paints. On agutterchange, the DOM will briefly render with stale cached item positions (the exact bug this workaround targets) before the effect fires and corrects them, causing a one-frame flicker. Community workarounds for this same TanStack Virtual caching issue useuseLayoutEffectspecifically to flush the remeasure synchronously before paint.🎨 Proposed fix
-import { useEffect, useRef, useState } from 'react'; +import { useLayoutEffect, useEffect, useRef, useState } from 'react'; ... const prevGutter = useRef(gutter); - useEffect(() => { + useLayoutEffect(() => { if (prevGutter.current !== gutter) { prevGutter.current = gutter; virtualizer.measure(); } }, [gutter, virtualizer]);Note: keep
useEffectfor the unrelatedsetMountedeffect above; only this remeasure effect benefits from the layout-timing change.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package/src/hooks/useMasonry.ts` around lines 128 - 136, The gutter-change remeasure in useMasonry is running too late in a passive effect, which can cause a one-frame flash of stale virtualized spacing. Change the specific effect that compares prevGutter.current and calls virtualizer.measure() from useEffect to useLayoutEffect so the remeasure happens before paint, while keeping the separate setMounted effect as useEffect. Use the existing symbols prevGutter, gutter, and virtualizer to locate the exact block.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@package/src/hooks/useMasonry.ts`:
- Around line 128-136: The gutter-change remeasure in useMasonry is running too
late in a passive effect, which can cause a one-frame flash of stale virtualized
spacing. Change the specific effect that compares prevGutter.current and calls
virtualizer.measure() from useEffect to useLayoutEffect so the remeasure happens
before paint, while keeping the separate setMounted effect as useEffect. Use the
existing symbols prevGutter, gutter, and virtualizer to locate the exact block.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: bec07e72-22f7-42d6-91d9-928a97796b48
📒 Files selected for processing (3)
.changeset/purple-seas-thank.mdpackage/src/hooks/useMasonry.test.tsxpackage/src/hooks/useMasonry.ts
Dynamic
gutterchanges were not applied — virtual-core doesn't invalidate its measurement cache whengapchanges (TanStack/virtual#1222).Workaround: call
virtualizer.measure()whengutterchanges, forcing a re-layout. Covered by a test asserting it fires only on actual gutter changes.Revert once the upstream fix lands.
Summary by CodeRabbit
Bug Fixes
Tests
Chores