Skip to content

Expose API to update size cache for VList/Virtualizer #885

Description

@Horuse

Is your feature request related to a problem? Please describe.

With variable-height items in <VList> / <Virtualizer>, a drag-and-drop reorder produces a one-frame flicker (~1-2px shift, sometimes more) before the layout settles.

virtua's size cache is keyed by index (Cache._sizes[i] in src/core/cache.ts), so after reordering items in the data array the same index points to a different item with a different real height.

  1. User updates data, so the same index now references a different item.
  2. virtua renders with the stale cached height (_sizes[index]).
  3. ResizeObserver delivers new sizes, ACTION_ITEM_RESIZE in
    src/core/store.ts computes a jump and bumps stateVersion.
  4. The effect tied to stateVersion calls scroller.$fixScrollJump(),
    writing scrollTop += jump.
  5. Browser already painted one frame with stale heights, hence the flicker.

Lists with uniform heights don't reproduce this because cached values remain valid after permutation. The repo's existing dnd-kit story uses uniform heights, which is why it doesn't surface the issue.

Describe the solution you'd like

Some way to update the index/size mapping from user code before the reorder lands, so that the subsequent ResizeObserver callback finds the cache already consistent and skips its correction pass.

for example:

vlist.setItemSizes([[0, h0], [1, h1], ...]);

Describe alternatives you've considered

  • requestAnimationFrame + scrollBy(delta). Always lands at least
    one frame after virtua's own $fixScrollJump, leaving sub-pixel jitter.
  • scrollTo(getScrollOffset()) save/restore. Produces an extra scroll
    event, perceived as double jitter.

Additional context

Example (virtua + dnd-kit): https://stackblitz.com/edit/vitejs-vite-4xibpcqs?file=src%2FApp.tsx

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions