Skip to content

Commit 9160010

Browse files
adamivanczameta-codesync[bot]
authored andcommitted
Fix ScrollView recycled content inset (#57494)
Summary: Fixes #57314. When a Fabric `ScrollView` is recycled on iOS, `prepareForRecycle` resets native scroll state before the view is reused. `contentInset` was being reset to `UIEdgeInsetsZero`, which prevents stale native insets from leaking between recycled views, but also drops a valid non-zero `contentInset` from the current props. If the recycled view is mounted again with the same `contentInset` prop value, `updateProps` may not reapply it because the props did not change. This can leave the native `UIScrollView` with `contentInset = 0` even though React props still specify a non-zero inset. This change keeps the stale-state protection, but resets `contentInset` back to the value from the current props instead of always zeroing it. ## Changelog: [IOS] [FIXED] - Preserve Fabric ScrollView contentInset when recycling iOS native views Pull Request resolved: #57494 Test Plan: Verified with the repro from #57314: 1. Cloned and installed `gimi-anders/rn-contentinset-recycle-repro` 2. Ran the app with the existing implementation and reproduced the issue: - Step 0: first ScrollView reports `native contentInset.top = 200` - Step 1: first ScrollView is unmounted - Step 2: recycled ScrollView reports `native contentInset.top = 0` 3. Applied this change to the repro app’s local React Native source and rebuilt with React Native Core built from source. 4. Re-ran the repro: - Step 2 now reports `native contentInset.top = 200` Also verified that the previous stale-inset protection is preserved: `prepareForRecycle` still overwrites the recycled native `UIScrollView.contentInset`; it now overwrites it with the current props value instead of always using `UIEdgeInsetsZero`. | Before | After | | --- | --- | | https://github.com/user-attachments/assets/e69ce800-23ab-4406-8700-f57511af85d8 | https://github.com/user-attachments/assets/35b93cff-0804-455c-a85c-2c0b05d35417 | Reviewed By: cipolleschi Differential Revision: D111262993 Pulled By: javache fbshipit-source-id: a98729d105792c51a7dec6eee8510cfd086e372e
1 parent 102fde7 commit 9160010

1 file changed

Lines changed: 1 addition & 2 deletions

File tree

packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,7 @@ - (void)prepareForRecycle
696696
// Invalidate cached content size so that updateState: recalculates the
697697
// container frame after zoomScale reset (which may have mutated it in RTL).
698698
_contentSize = CGSizeZero;
699-
// Reset contentInset to prevent stale insets leaking into recycled scroll views.
700-
_scrollView.contentInset = UIEdgeInsetsZero;
699+
_scrollView.contentInset = RCTUIEdgeInsetsFromEdgeInsets(props.contentInset);
701700
// We set the default behavior to "never" so that iOS
702701
// doesn't do weird things to UIScrollView insets automatically
703702
// and keeps it as an opt-in behavior.

0 commit comments

Comments
 (0)