feat(virtual-core): add deferLaneAssignment option#1115
feat(virtual-core): add deferLaneAssignment option#11152wheeh wants to merge 3 commits intoTanStack:mainfrom
Conversation
🦋 Changeset detectedLatest commit: 3501a23 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
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 |
There was a problem hiding this comment.
Pull request overview
Adds a new deferLaneAssignment option to @tanstack/virtual-core to support masonry-style layouts where lane assignment should be derived from measured sizes (via measureElement/resizeItem) rather than estimateSize, while keeping the existing “stable lanes via caching” behavior as the default.
Changes:
- Introduces
deferLaneAssignment?: boolean(defaultfalse) and conditionally skips lane caching until an item has been measured. - Adds tests covering deferred vs immediate lane caching behavior.
- Updates API docs and adds a changeset for release.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/virtual-core/src/index.ts | Adds deferLaneAssignment option + logic to skip caching lanes for unmeasured items |
| packages/virtual-core/tests/index.test.ts | Adds regression tests for deferred/immediate lane caching |
| docs/api/virtualizer.md | Documents new option and clarifies lane caching behavior |
| docs/api/virtual-item.md | Updates lane documentation to mention caching + deferral option |
| .changeset/loud-insects-itch.md | Publishes the change as a patch release |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Check if this item has been measured (for deferLaneAssignment mode) | ||
| const isMeasured = itemSizeCache.has(key) | ||
| const shouldDeferLane = this.options.deferLaneAssignment && !isMeasured | ||
|
|
There was a problem hiding this comment.
deferLaneAssignment affects how getMeasurements assigns/caches lanes, but getMeasurements is memoized and its deps don’t include this option (via getMeasurementOptions). If setOptions toggles deferLaneAssignment, getMeasurements may return the cached result and/or keep stale laneAssignments, so the new behavior won’t take effect. Include deferLaneAssignment in the memo dependency list (and consider clearing/rebuilding laneAssignments when it changes) so runtime option updates behave correctly.
| ``` | ||
|
|
||
| The lane index of the item. In regular lists it will always be set to `0` but becomes useful for masonry layouts (see variable examples for more details). | ||
| The lane index of the item. Items are assigned to the shortest lane. Lane assignments are cached immediately based on the size measured by `estimateSize` by default; use `deferLaneAssignment: true` to base assignments on measured sizes instead. |
There was a problem hiding this comment.
The wording “size measured by estimateSize” is inaccurate—estimateSize provides an estimate, not a measurement. Consider rephrasing to “size estimated by estimateSize” to avoid implying it’s based on DOM measurement.
| The lane index of the item. Items are assigned to the shortest lane. Lane assignments are cached immediately based on the size measured by `estimateSize` by default; use `deferLaneAssignment: true` to base assignments on measured sizes instead. | |
| The lane index of the item. Items are assigned to the shortest lane. Lane assignments are cached immediately based on the size estimated by `estimateSize` by default; use `deferLaneAssignment: true` to base assignments on measured sizes instead. |
🎯 Changes
resolves #1114
Adds
deferLaneAssignmentoption to defer lane caching until items are measured viameasureElement.#1080 introduced lane assignment caching based on
estimateSizefor visual stability. However, this broke a core use case for masonry layouts where lane assignments should be based on actual measured sizes, not estimates.This PR adds a new option
deferLaneAssignment(default:false):false(default): Current behavior - lanes cached immediately fromestimateSizetrue: Lanes are calculated but not cached until first measurement, then cached based on actual sizes✅ Checklist
pnpm run test:pr.🚀 Release Impact