Skip to content

Commit 21b93d8

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Fix RefreshControl recycling (#52584)
Summary: Pull Request resolved: #52584 The method `_initializeUIRefreshControl` creates a new instance of `UIRefreshControl` which has the default values for things like tint color. However the props that we are keeping in the component are the `_props` before recycling. The actual state of the newly created UIRefreshControl is out of sync w.r.t the props the component thinks to have. By introducing a `_recycled` state variable, we can force the first `updateProp` call to apply all the props to the newly created component. ## Changelog: [iOS][Fixed] - Make sure that the recycled refresh control have the right props setup. Reviewed By: sammy-SC Differential Revision: D78278207 fbshipit-source-id: 4be20aa43f96eb87828b44a4deedd33a23d1d17f
1 parent 09daad2 commit 21b93d8

1 file changed

Lines changed: 16 additions & 7 deletions

File tree

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

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ @interface RCTPullToRefreshViewComponentView () <RCTPullToRefreshViewViewProtoco
2626
@implementation RCTPullToRefreshViewComponentView {
2727
UIRefreshControl *_refreshControl;
2828
RCTScrollViewComponentView *__weak _scrollViewComponentView;
29+
// This variable keeps track of whether the view is recycled or not. Once the view is recycled, the component
30+
// creates a new instance of UIRefreshControl, resetting the native props to the default values.
31+
// However, when recycling, we are keeping around the old _props. The flag is used to force the application
32+
// of the current props to the newly created UIRefreshControl the first time that updateProps is called.
33+
BOOL _recycled;
2934
}
3035

3136
- (instancetype)initWithFrame:(CGRect)frame
@@ -35,6 +40,7 @@ - (instancetype)initWithFrame:(CGRect)frame
3540
// attaching and detaching of a pull-to-refresh view to a scroll view.
3641
// The pull-to-refresh view is not a subview of this view.
3742
self.hidden = YES;
43+
_recycled = NO;
3844
[self _initializeUIRefreshControl];
3945
}
4046

@@ -61,49 +67,52 @@ - (void)prepareForRecycle
6167
[super prepareForRecycle];
6268
_scrollViewComponentView = nil;
6369
[self _initializeUIRefreshControl];
70+
_recycled = YES;
6471
}
6572

6673
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
6774
{
6875
const auto &oldConcreteProps = static_cast<const PullToRefreshViewProps &>(*_props);
6976
const auto &newConcreteProps = static_cast<const PullToRefreshViewProps &>(*props);
7077

71-
if (newConcreteProps.tintColor != oldConcreteProps.tintColor) {
78+
if (_recycled || newConcreteProps.tintColor != oldConcreteProps.tintColor) {
7279
_refreshControl.tintColor = RCTUIColorFromSharedColor(newConcreteProps.tintColor);
7380
}
7481

75-
if (newConcreteProps.progressViewOffset != oldConcreteProps.progressViewOffset) {
82+
if (_recycled || newConcreteProps.progressViewOffset != oldConcreteProps.progressViewOffset) {
7683
[self _updateProgressViewOffset:newConcreteProps.progressViewOffset];
7784
}
7885

7986
BOOL needsUpdateTitle = NO;
8087

81-
if (newConcreteProps.title != oldConcreteProps.title) {
88+
if (_recycled || newConcreteProps.title != oldConcreteProps.title) {
8289
needsUpdateTitle = YES;
8390
}
8491

85-
if (newConcreteProps.titleColor != oldConcreteProps.titleColor) {
92+
if (_recycled || newConcreteProps.titleColor != oldConcreteProps.titleColor) {
8693
needsUpdateTitle = YES;
8794
}
8895

8996
[super updateProps:props oldProps:oldProps];
9097

91-
if (needsUpdateTitle) {
98+
if (_recycled || needsUpdateTitle) {
9299
[self _updateTitle];
93100
}
94101

95102
// All prop updates must happen above the call to begin refreshing, or else _refreshControl will ignore the updates
96-
if (newConcreteProps.refreshing != oldConcreteProps.refreshing) {
103+
if (_recycled || newConcreteProps.refreshing != oldConcreteProps.refreshing) {
97104
if (newConcreteProps.refreshing) {
98105
[self beginRefreshingProgrammatically];
99106
} else {
100107
[_refreshControl endRefreshing];
101108
}
102109
}
103110

104-
if (newConcreteProps.zIndex != oldConcreteProps.zIndex) {
111+
if (_recycled || newConcreteProps.zIndex != oldConcreteProps.zIndex) {
105112
_refreshControl.layer.zPosition = newConcreteProps.zIndex.value_or(0);
106113
}
114+
115+
_recycled = NO;
107116
}
108117

109118
#pragma mark -

0 commit comments

Comments
 (0)