镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Dynamic item sizes are not recalculated after reordering #1084

Closed as not planned

Description

@Misha6787

Describe the bug

In a virtualized list using @tanstack/vue-virtual, reordering items with dynamic or varying sizes (e.g., different heights) does not trigger a recalculation of their cached measurements. As a result, the items retain their initial rendered dimensions post-reorder, leading to visual artifacts such as:

  • Larger items being clipped or overflowing within the constrained space originally allocated to smaller items.
  • Smaller items leaving empty gaps due to mismatched container sizes.

Your minimal, reproducible example

https://stackblitz.com/edit/tanstack-virtual-xbv5kvkh?file=src%2FApp.vue

Steps to reproduce

  1. Click the Swap button
  2. Look at the list's second and third items

Expected behavior

After reordering, the virtualizer should re-measure and update the sizes for affected items

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • Windows - Chrome - v.142.0.7444.61

tanstack-virtual version

v3.13.12

TypeScript version

v5.4.5

Additional context

No response

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

Activity

  1. ilyarefraction commented on Dec 1, 2025

    @ilyarefraction

    This issue can be "fixed" in the userland by calling virtualizer.measure() when the ordering in the item list is changed. The issues are:

    1. The performance drawbacks are unclear
    2. Reordering detection looks like a pretty low-level code, which can be written in the library itself

    IMO, ideally, the library should automatically handle size recalculation during reordering

  2. ilyarefraction commented on Dec 1, 2025

    @ilyarefraction

    I found a reference where @piecyk recommends using useCallback to solve a (looks like) similar issue. In vue, however, we don't have such an API and rely on a smarter reactivity system rather than handling dependencies manually.

  3. piecyk commented on Oct 14, 2026

    @piecyk
    Collaborator

    The measurement cache is keyed by getItemKey, which defaults to the index, so after a reorder positions keep their old sizes (and nothing resizes, so ResizeObserver doesn't fire). Use a stable key, e.g. getItemKey: (i) => items.value[i].id; a new getItemKey invalidates the measurements. Calling virtualizer.measure() after a reorder also works. Please reopen with an updated repro if it still breaks with a stable key.

  4. Misha6787 commented on Oct 22, 2026

    @Misha6787
    Author

    @piecyk Thanks for the response. I added the use of getItemKey: (i) => items.value[i].id, but that didn't help.

    The option using getItemKey: (i) => items.value[i].id - https://stackblitz.com/edit/tanstack-virtual-jcjdebwx

    UPD:
    For some reason I can't reopen the issue(

  5. piecyk commented on Oct 22, 2026

    @piecyk
    Collaborator

    Thanks for the repro. It doesn't use measureElement, so every size comes from estimateSize. getItemKey only keys measured sizes, so it has no effect here, and the virtualizer can't tell that estimateSize(i) now returns something different. Two options:

    1. Measure the rows: :ref="rowVirtualizer.measureElement" + :data-index="virtualRow.index" on the row (and drop the fixed height). With getItemKey by id, the sizes follow the items after a swap.
    2. Keep estimates and call rowVirtualizer.value.measure() after the swap.

    Also, :key="virtualRow.id" should be virtualRow.key, and pass the options as a computed so count stays reactive.

  6. Misha6787 commented on Oct 24, 2026

    @Misha6787
    Author

    @piecyk It works! Thank you very much for your help.

    Just in case, I’ll leave a link to the version with your edits in this comment. It might come in handy for someone.

    https://stackblitz.com/edit/tanstack-virtual-jcjdebwx

    UPD: I forgot to mention that I used option 1 to fix the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions