Skip to content

Commit 433ab12

Browse files
committed
Fix infinite render loop by guaranteeing layout commit
1 parent 921847d commit 433ab12

1 file changed

Lines changed: 38 additions & 9 deletions

File tree

src/recyclerview/RecyclerView.tsx

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ const RecyclerViewComponent = <T,>(
9393

9494
renderTimeTracker.startTracking();
9595

96+
const layoutRetryCountRef = useRef(0);
97+
const MAX_LAYOUT_RETRIES = 5;
98+
99+
96100
// Sticky header config
97101
const stickyHeaderOffset = stickyHeaderConfig?.offset ?? 0;
98102
const stickyHeaderUseNativeDriver =
@@ -183,7 +187,7 @@ const RecyclerViewComponent = <T,>(
183187
},
184188
isHorizontalRTL && recyclerViewManager.hasLayout()
185189
? firstItemOffset -
186-
recyclerViewManager.getChildContainerDimensions().width
190+
recyclerViewManager.getChildContainerDimensions().width
187191
: firstItemOffset
188192
);
189193
}
@@ -227,17 +231,42 @@ const RecyclerViewComponent = <T,>(
227231
console.warn(WarningMessages.exceededMaxRendersWithoutCommit);
228232
}
229233

230-
if (
231-
recyclerViewManager.modifyChildrenLayout(layoutInfo, data?.length ?? 0) &&
232-
!hasExceededMaxRendersWithoutCommit
233-
) {
234-
// Trigger re-render if layout modifications were made
235-
setRenderId((prev) => prev + 1);
234+
// if (
235+
// recyclerViewManager.modifyChildrenLayout(layoutInfo, data?.length ?? 0) &&
236+
// !hasExceededMaxRendersWithoutCommit
237+
// ) {
238+
// // Trigger re-render if layout modifications were made
239+
// setRenderId((prev) => prev + 1);
240+
// } else {
241+
// viewHolderCollectionRef.current?.commitLayout();
242+
// applyOffsetCorrection();
243+
// }
244+
245+
const layoutChanged = recyclerViewManager.modifyChildrenLayout(
246+
layoutInfo,
247+
data?.length ?? 0
248+
);
249+
250+
if (layoutChanged && !hasExceededMaxRendersWithoutCommit) {
251+
layoutRetryCountRef.current += 1;
252+
253+
if (layoutRetryCountRef.current <= MAX_LAYOUT_RETRIES) {
254+
// Allow a few retries to stabilize layout
255+
setRenderId((prev) => prev + 1);
256+
} else {
257+
// Force convergence: commit layout and reset
258+
layoutRetryCountRef.current = 0;
259+
viewHolderCollectionRef.current?.commitLayout();
260+
applyOffsetCorrection();
261+
}
236262
} else {
263+
// Layout is stable
264+
layoutRetryCountRef.current = 0;
237265
viewHolderCollectionRef.current?.commitLayout();
238266
applyOffsetCorrection();
239267
}
240268

269+
241270
if (
242271
horizontal &&
243272
recyclerViewManager.hasLayout() &&
@@ -585,8 +614,8 @@ const RecyclerViewComponent = <T,>(
585614
return Math.max(
586615
0,
587616
windowSize -
588-
childContainerSize -
589-
recyclerViewManager.firstItemOffset
617+
childContainerSize -
618+
recyclerViewManager.firstItemOffset
590619
);
591620
}}
592621
refHolder={refHolder}

0 commit comments

Comments
 (0)