Skip to content

Commit f86459c

Browse files
committed
Fix infinite render loop by guaranteeing layout commit
Refactor layout retry logic to improve readability and convergence clarity
1 parent 921847d commit f86459c

1 file changed

Lines changed: 31 additions & 10 deletions

File tree

src/recyclerview/RecyclerView.tsx

Lines changed: 31 additions & 10 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,16 +231,33 @@ 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);
236-
} else {
234+
const layoutChanged = recyclerViewManager.modifyChildrenLayout(
235+
layoutInfo,
236+
data?.length ?? 0
237+
);
238+
239+
const shouldRetryLayout =
240+
layoutChanged && !hasExceededMaxRendersWithoutCommit;
241+
242+
const commitLayoutAndCorrectOffset = () => {
243+
layoutRetryCountRef.current = 0;
237244
viewHolderCollectionRef.current?.commitLayout();
238245
applyOffsetCorrection();
246+
};
247+
248+
249+
if (shouldRetryLayout) {
250+
layoutRetryCountRef.current += 1;
251+
252+
if (layoutRetryCountRef.current <= MAX_LAYOUT_RETRIES) {
253+
// Retry render to stabilize layout
254+
setRenderId((prev) => prev + 1);
255+
return;
256+
}
239257
}
258+
// Commit path: layout is stable OR retries exhausted
259+
commitLayoutAndCorrectOffset();
260+
240261

241262
if (
242263
horizontal &&
@@ -585,8 +606,8 @@ const RecyclerViewComponent = <T,>(
585606
return Math.max(
586607
0,
587608
windowSize -
588-
childContainerSize -
589-
recyclerViewManager.firstItemOffset
609+
childContainerSize -
610+
recyclerViewManager.firstItemOffset
590611
);
591612
}}
592613
refHolder={refHolder}

0 commit comments

Comments
 (0)