virtual icon indicating copy to clipboard operation
virtual copied to clipboard

Virtualizer does not update after adjusting row height

Open theo-champlin opened this issue 2 years ago • 8 comments

Describe the bug

Building on the dynamic example, I added a timeout to update the height of rows. The element size updated but the positions did not.

Your minimal, reproducible example

https://codesandbox.io/s/delicate-river-3rigv0?file=/src/main.tsx

Steps to reproduce

Wait for the timeout, see broken table.

Expected behavior

As the size of rows update, the position of the rows should be adjusted.

How often does this bug happen?

Every time

Screenshots or Videos

https://user-images.githubusercontent.com/40192128/185458840-b3020220-63de-49ff-adb9-16e67d63030d.mov

Platform

I tested on Firefox and Chrome on macOS 12.5

tanstack-virtual version

3.0.0

TypeScript version

No response

Additional context

No response

Terms & Code of Conduct

  • [X] I agree to follow this project's Code of Conduct
  • [X] 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.

theo-champlin avatar Aug 18 '22 17:08 theo-champlin

We are something different, where the orthogonal (width) changes causes the row heights to change, but translateYs doesn't update, even if we force a re-render.

we are still on 2.9.0 though, so maybe there already is a fix?

maybe more accurately described as: https://github.com/TanStack/virtual/issues/323

henrikq avatar Aug 19 '22 07:08 henrikq

@theo-champlin I submitted a PR to fix the issue (#377). I had the same problem when adjusting a column width, some rows where not being remeasured when they changed the height.

carlosbaraza avatar Aug 21 '22 10:08 carlosbaraza

I had the same problem, I manually call a function to recompute sizes after element size change

function recomputeSizes(){
    instance.getVirtualItems().forEach((virtualItem, index) => {
      virtualItem.measureElement(listElement.children[index]);
    });
}

arash-es avatar Aug 21 '22 15:08 arash-es

I had the same problem, I manually call a function to recompute sizes after element size change

function recomputeSizes(){
    instance.getVirtualItems().forEach((virtualItem, index) => {
      virtualItem.measureElement(listElement.children[index]);
    });
}

This workaround does work. I have a dynamic list that is filtered by a text input. What seems to fix the issue there is

    useLayoutEffect(() => {
        selectedRowVirtualizer.getVirtualItems().forEach((virtualItem, index) => {
            virtualItem.measureElement(selectedListRef.current.children[index]);
        });
    }, [selectedRowVirtualizer, selectedMembers.length, selectedInvitations.length]);

As soon as the filtered elements change, a side effect triggers the measurement.

Mario-Eis avatar Aug 22 '22 13:08 Mario-Eis

Is there any official fix for this? Our production site features live updating rows with thousands of items. Measuring each element individually is not ideal for performance reasons.

KosGrillis avatar Aug 25 '22 19:08 KosGrillis

@theo-champlin @KosGrillis this is what you might be looking for https://github.com/TanStack/virtual/issues/28#issuecomment-817182500

AgarwalPragy avatar Aug 25 '22 19:08 AgarwalPragy

My solution when row height changes due to table width change (layout)

  const [tableRect, tableRef] = useBoundingClientRectRef(['width']);
  const width = Math.round(tableRect?.width);
  useEffect(() => rowVirtualizer.measure(), [rowVirtualizer, width]);

useBoundingClientRectRef is a hook version of ResizeObserver, MutationObserver and getBoundingClientRect.

henrikq avatar Aug 31 '22 05:08 henrikq

@KosGrillis Its a virtual list. Only visible items (plus overscan I guess) are measured. As virtual lists are positioned absolute, I would say there is no way of avoiding the measurement. The official fix would measure internally. If this is not what you want, a fixed list is what you are looking for.

Mario-Eis avatar Sep 09 '22 08:09 Mario-Eis

Unfortunately this issues still exists. At least in my case, the workaround from https://github.com/TanStack/virtual/issues/376#issuecomment-1222346322 is still needed.

Initially the size is correct now. But I have buttons in the virtual list. Clicking a button removes the item from the list. As soon as this happens, the dynamic entry sizes are wrong again.

Mario-Eis avatar Nov 09 '22 15:11 Mario-Eis

@Mario-Eis hard to say what is happening without minimal example, are you setting correct key for the row? Default we use index as key, then in case of removing maybe it could break something.

piecyk avatar Nov 09 '22 15:11 piecyk