Skip to content

Commit

Permalink
Fix momentum begin dispatch order (facebook#47578)
Browse files Browse the repository at this point in the history
Summary:

In `RCTScrollView`, it was possible that `onMomentumScrollBegin` gets queued after `onMomentumScrollEnd` because the event would dispatch after calling `setContentOffset`. As a result, the ScrollView JS gets stuck in an "animating" state and jest runners did not bother scrolling further.

## Changelog:
[iOS][Fixed] - Momentum begin events now queue before momentum end events on scroll views

Differential Revision: D65846878
  • Loading branch information
Abbondanzo authored and facebook-github-bot committed Nov 12, 2024
1 parent d3c5446 commit f0802a6
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -897,14 +897,18 @@ - (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated

[self _forceDispatchNextScrollEvent];

// Notify of momentum scroll begin before setting content offset or events can fire out of order and scrollview gets
// stuck in "animating" state
if (animated && _eventEmitter) {
static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onMomentumScrollBegin([self _scrollViewMetrics]);
}

[_scrollView setContentOffset:offset animated:animated];

if (!animated) {
// When not animated, the expected workflow in ``scrollViewDidEndScrollingAnimation`` after scrolling is not going
// to get triggered. We will need to manually execute here.
[self _handleFinishedScrolling:_scrollView];
} else if (_eventEmitter) {
static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onMomentumScrollBegin([self _scrollViewMetrics]);
}
}

Expand Down
8 changes: 6 additions & 2 deletions packages/react-native/React/Views/ScrollView/RCTScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,12 @@ - (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated
y = fmin(y, CGRectGetMaxY(maxRect));
offset = CGPointMake(x, y);
}
[_scrollView setContentOffset:offset animated:animated];
// Notify of momentum scroll begin before setting content offset or events can fire out of order and scrollview gets
// stuck in "animating" state
if (animated) {
[self sendScrollEventWithName:@"onMomentumScrollBegin" scrollView:_scrollView userData:nil];
}
[_scrollView setContentOffset:offset animated:animated];
}
}

Expand All @@ -624,10 +626,12 @@ - (void)scrollToEnd:(BOOL)animated
if (!CGPointEqualToPoint(_scrollView.contentOffset, offset)) {
// Ensure at least one scroll event will fire
_allowNextScrollNoMatterWhat = YES;
[_scrollView setContentOffset:offset animated:animated];
// Notify of momentum scroll begin before setting content offset or events can fire out of order and scrollview gets
// stuck in "animating" state
if (animated) {
[self sendScrollEventWithName:@"onMomentumScrollBegin" scrollView:_scrollView userData:nil];
}
[_scrollView setContentOffset:offset animated:animated];
}
}

Expand Down

0 comments on commit f0802a6

Please sign in to comment.