Commit d50c1b5
Fix recycled ScrollView inheriting stale contentInset on iOS (#56832)
Summary:
Fixes #55090
In Fabric, `prepareForRecycle` resets contentInset to zero when a `ScrollView` is recycled. But the subsequent frame reset dance (required for `contentInsetAdjustmentBehavior` see 27fe6f1) triggers `centerContentIfNeeded` with the previous component's stale content size, silently overwriting the reset.
As a result, a `ScrollView` with `centerContent={true}` that is unmounted and replaced by another `ScrollView` leaves behind a stale contentInset that the new component inherits causing displaced content if the new `ScrollView` does not have `centerContent={true}`.
Two fixes:
1. `RCTScrollViewComponentView`
In updateProps, when `centerContent` transitions from true to false, explicitly reset `contentInset` to the prop value. `centerContentIfNeeded` will not self-correct once `centerContent` is disabled on the new component, so the reset must be forced. The existing `contentInset` prop check is also guarded with !centerContent to prevent it from overriding the inset calculated by centerContentIfNeeded when centering is active.
2. `RCTEnhancedScrollView`
Override `setCenterContent:` and `setContentSize:` to trigger `centerContentIfNeeded`. This ensures centering is re-applied with the correct new content size when the new component's content arrives via `updateState:`, and that toggling `centerContent` takes effect immediately.
## Changelog:
[IOS] [FIXED] - Fix recycled ScrollView inheriting stale contentInset from centerContent on Fabric
Pull Request resolved: #56832
Test Plan:
Using the RNTester-app, replace `CenterContentList` with the following inside `ScrollViewExample.js`:
<details><summary>CenterContentList reproducer</summary>
Doing two different ScrollViews to force an unmount of the one with centerContent so the other inherits its insets
```jsx
function CenterContentList(): React.Node {
const [centerContent, setCenterContent] = useState(true);
if (centerContent) {
return (
<ScrollView
nestedScrollEnabled
style={styles.scrollView}
centerContent={true}>
<Text>This should be in center.</Text>
<Button
label="Toggle centerContent"
onPress={() => setCenterContent(!centerContent)}
/>
</ScrollView>
);
} else {
return (
<ScrollView
nestedScrollEnabled
style={styles.scrollView}
centerContent={false}>
<Text>This should not be in center.</Text>
<Button
label="Toggle centerContent"
onPress={() => setCenterContent(!centerContent)}
/>
</ScrollView>
);
}
}
```
</details>
### Before the fix
Note that for both `ScrollView`s the content is centered, even though one has `centerContent={false}`.
https://github.com/user-attachments/assets/7d5916a2-dbe3-4955-ad7b-1e6596d90104
### After the fix
One is properly centered, while the other has its content at the top.
https://github.com/user-attachments/assets/ae8a41eb-0084-40e7-98fd-88433956ea40
Reviewed By: cipolleschi
Differential Revision: D105294296
Pulled By: javache
fbshipit-source-id: 4dfd2ecddb2c381e204da3a9278e74829ea702b51 parent 3a3a648 commit d50c1b5
2 files changed
Lines changed: 25 additions & 2 deletions
File tree
- packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView
Lines changed: 14 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
105 | 119 | | |
106 | 120 | | |
107 | 121 | | |
| |||
Lines changed: 11 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
396 | 396 | | |
397 | 397 | | |
398 | 398 | | |
399 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
400 | 402 | | |
401 | 403 | | |
402 | 404 | | |
403 | | - | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
404 | 410 | | |
405 | 411 | | |
406 | 412 | | |
407 | 413 | | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
408 | 417 | | |
409 | 418 | | |
410 | 419 | | |
| |||
0 commit comments