virtual
virtual copied to clipboard
Virtualizer does not update after adjusting row height
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.
We are something different, where the orthogonal (width) changes causes the row heights to change, but translateY
s 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
@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.
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]);
});
}
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.
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.
@theo-champlin @KosGrillis this is what you might be looking for https://github.com/TanStack/virtual/issues/28#issuecomment-817182500
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.
@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.
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 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.