@@ -58,6 +58,41 @@ static UIScrollViewIndicatorStyle RCTUIScrollViewIndicatorStyleFromProps(const S
5858 }
5959}
6060
61+ // Child clipping only depends on which descendants exist and their layout frames.
62+ // A mounting transaction that contains only prop updates with unchanged layout
63+ // metrics (e.g. opacity/transform commits from Reanimated, which fire every
64+ // animation frame) cannot change clipping, so re-clipping can be skipped.
65+ static BOOL RCTMountingTransactionAffectsClipping (const facebook::react::MountingTransaction &transaction)
66+ {
67+ for (const auto &mutation : transaction.getMutations ()) {
68+ switch (mutation.type ) {
69+ case facebook::react::ShadowViewMutation::Insert:
70+ case facebook::react::ShadowViewMutation::Remove:
71+ return YES ;
72+ case facebook::react::ShadowViewMutation::Update: {
73+ const auto &oldChild = mutation.oldChildShadowView ;
74+ const auto &newChild = mutation.newChildShadowView ;
75+ if (oldChild.layoutMetrics != newChild.layoutMetrics ) {
76+ return YES ;
77+ }
78+ // A `removeClippedSubviews` toggle changes clipping without changing
79+ // layout, so it must also force a re-clip.
80+ if (oldChild.props && newChild.props ) {
81+ const auto &oldProps = static_cast <const facebook::react::ViewProps &>(*oldChild.props );
82+ const auto &newProps = static_cast <const facebook::react::ViewProps &>(*newChild.props );
83+ if (oldProps.removeClippedSubviews != newProps.removeClippedSubviews ) {
84+ return YES ;
85+ }
86+ }
87+ break ;
88+ }
89+ default :
90+ break ;
91+ }
92+ }
93+ return NO ;
94+ }
95+
6196// Once Fabric implements proper NativeAnimationDriver, this should be removed.
6297// This is just a workaround to allow animations based on onScroll event.
6398// This is only used to animate sticky headers in ScrollViews, and only the contentOffset and tag is used.
@@ -292,7 +327,9 @@ - (void)mountingTransactionWillMount:(const facebook::react::MountingTransaction
292327- (void )mountingTransactionDidMount : (const MountingTransaction &)transaction
293328 withSurfaceTelemetry : (const facebook::react::SurfaceTelemetry &)surfaceTelemetry
294329{
295- [self _remountChildren ];
330+ if (RCTMountingTransactionAffectsClipping (transaction)) {
331+ [self _remountChildren ];
332+ }
296333 [self _adjustForMaintainVisibleContentPosition ];
297334}
298335
0 commit comments