Skip to content

Commit 348c9ea

Browse files
authored
fix(scroll): read initialScrollIndex offset after layout recompute (#2133)
* fix(scroll): read initialScrollIndex offset after layout recompute In applyInitialScrollAdjustment(), the scroll offset for the target initialScrollIndex item was read before recomputeLayouts() ran. The recompute re-estimates unmeasured items with updated average heights, which shifts the target item's y position. The stale offset caused a mismatch between the EngagedIndicesTracker's scroll position and the actual item positions, resulting in blank screens or overlapping items when initialScrollIndex was set with variable-height items. Move the offset read to after recomputeLayouts() so the scroll offset always reflects the target item's actual position. Also fixes a minor operator precedence issue in the nullish coalescing fallback. Includes a fixture repro screen (OverlapRepro) with 200 variable-height items (40-500px) and initialScrollIndex=50. Fixes #1797 * Remove OverlapRepro sample screen
1 parent e81f4ef commit 348c9ea

File tree

1 file changed

+15
-16
lines changed

1 file changed

+15
-16
lines changed

src/recyclerview/RecyclerViewManager.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -382,27 +382,26 @@ export class RecyclerViewManager<T> {
382382
}
383383

384384
const initialScrollIndex = this.getInitialScrollIndex();
385-
const initialItemLayout = this.layoutManager?.getLayout(
386-
initialScrollIndex ?? 0
387-
);
388-
const initialItemOffset = this.propsRef.horizontal
389-
? initialItemLayout?.x
390-
: initialItemLayout?.y;
391385

392386
if (initialScrollIndex !== undefined) {
393-
// console.log(
394-
// "initialItemOffset",
395-
// initialScrollIndex,
396-
// initialItemOffset,
397-
// this.firstItemOffset
398-
// );
387+
// Recompute layouts first, then read the offset. The recompute may
388+
// re-estimate unmeasured items with an updated average height, changing
389+
// the target item's position. Reading before recompute would capture a
390+
// stale offset, causing the wrong items to be rendered.
399391
this.layoutManager.recomputeLayouts(0, initialScrollIndex);
400-
this.engagedIndicesTracker.scrollOffset =
401-
initialItemOffset ?? 0 + this.firstItemOffset;
392+
const initialItemLayout =
393+
this.layoutManager.getLayout(initialScrollIndex);
394+
const initialItemOffset = this.propsRef.horizontal
395+
? initialItemLayout.x
396+
: initialItemLayout.y;
397+
this.engagedIndicesTracker.scrollOffset = initialItemOffset;
402398
} else {
403-
// console.log("initialItemOffset", initialItemOffset, this.firstItemOffset);
399+
const initialItemLayout = this.layoutManager.getLayout(0);
400+
const initialItemOffset = this.propsRef.horizontal
401+
? initialItemLayout.x
402+
: initialItemLayout.y;
404403
this.engagedIndicesTracker.scrollOffset =
405-
(initialItemOffset ?? 0) - this.firstItemOffset;
404+
initialItemOffset - this.firstItemOffset;
406405
}
407406
}
408407

0 commit comments

Comments
 (0)