Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "fix: Ensure base virtualizer hooks recalc index if numItems changes",
"packageName": "@fluentui-contrib/react-virtualizer",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -517,9 +517,13 @@ export function useVirtualizer_unstable(
// Safety limits
const newStartIndex = Math.min(Math.max(startIndex, 0), maxIndex);
flushSync(() => {
// When the number of items change, we DO want to recalc even if at end of list
const numItemsChanged = previousNumItems.current !== numItems;
previousNumItems.current = numItems;
if (
newStartIndex + virtualizerLength >= numItems &&
actualIndex + virtualizerLength >= numItems
actualIndex + virtualizerLength >= numItems &&
!numItemsChanged
) {
// We've already hit the end, no need to update state.
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ export const useDynamicVirtualizerMeasure = <TElement extends HTMLElement>(
(scrollRef: React.MutableRefObject<HTMLElement | null>) => {
const hasReachedEnd =
virtualizerContext.contextIndex + virtualizerLength >= numItems;
if (!scrollRef?.current || hasReachedEnd) {
// Error? ignore?

// Track whether this update was driven by a change in numItems
const numItemsChanged = numItemsRef.current !== numItems;
numItemsRef.current = numItems;

if (!scrollRef?.current || (hasReachedEnd && !numItemsChanged)) {
return;
}

Expand All @@ -73,10 +77,9 @@ export const useDynamicVirtualizerMeasure = <TElement extends HTMLElement>(
/* If the numItems changed, we're going to calc
* a new index based on actual scroll position
*/
const actualScrollPos =
numItemsRef.current !== numItems
? _actualScrollPos
: scrollPosition.current;
const actualScrollPos = numItemsChanged
? _actualScrollPos
: scrollPosition.current;

const sizeToBeat = containerSizeRef.current + virtualizerBufferSize * 2;
const startIndex = Math.max(virtualizerContext.contextIndex, 0);
Expand Down Expand Up @@ -125,7 +128,7 @@ export const useDynamicVirtualizerMeasure = <TElement extends HTMLElement>(
const newBufferSize = bufferSize ?? Math.max(defaultItemSize / 2, 1);
const totalLength = length + newBufferItems * 2;

if (numItemsRef.current !== numItems && indexMod - newBufferItems > 0) {
if (numItemsChanged && indexMod - newBufferItems > 0) {
// Virtualizer will recalculate on numItems change, but from the old index
// We should get ahead of that update to prevent unnessecary recalculations
virtualizerContext.setContextIndex(
Expand All @@ -134,7 +137,6 @@ export const useDynamicVirtualizerMeasure = <TElement extends HTMLElement>(
}

scrollPosition.current = actualScrollPos;
numItemsRef.current = numItems;
setVirtualizerLength(totalLength);
setVirtualizerBufferItems(newBufferItems);
setVirtualizerBufferSize(newBufferSize);
Expand Down