Fix onContentSizeChange being dispatched too often on iOS (#49695)

Summary:
Solves the iOS part of https://github.com/facebook/react-native/issues/47186.

`onContentSizeChanged` event is sent inside the `updateLayoutMetrics` method every time it's invoked. A change in layout metrics doesn't mean that the content size also changes, like changing the position of the input.

This PR adds a condition that the content size must have changed before sending the event.

|Before this change|After this change|
|-|-|
|<video src="https://github.com/user-attachments/assets/743e1502-e13e-474e-b4a6-ef6873bf9619">|<video src="https://github.com/user-attachments/assets/fe3d3ef5-3951-4ba2-b9a1-c41439ab455c">|

In the reproducer from the issue, `SafeAreaView` is used, which at first renders its content without any insets until its state is updated with the correct insets. Both of these layouts change the layout metrics of the text input, resulting in two events before this change and a single one after.

## Changelog:

[IOS] [FIXED] - Fixed TextInput's `onContentSizeChange` event being dispatched multiple times with the same size

Pull Request resolved: https://github.com/facebook/react-native/pull/49695

Test Plan: Tested on the reproducer from the issue

Reviewed By: NickGerleman

Differential Revision: D70247460

Pulled By: j-piasecki

fbshipit-source-id: 8a1e0d0f55b6b3f8a6d0bb176ed50e47e3b51035
This commit is contained in:
Jakub Piasecki
2025-02-27 00:58:35 -08:00
committed by Facebook GitHub Bot
parent 8a4a6231b7
commit 2bb65717b7
@@ -327,6 +327,8 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
{
CGSize previousContentSize = _backedTextInputView.contentSize;
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
_backedTextInputView.frame =
@@ -334,7 +336,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
_backedTextInputView.textContainerInset =
RCTUIEdgeInsetsFromEdgeInsets(layoutMetrics.contentInsets - layoutMetrics.borderWidth);
if (_eventEmitter) {
if (!CGSizeEqualToSize(previousContentSize, _backedTextInputView.contentSize) && _eventEmitter) {
static_cast<const TextInputEventEmitter &>(*_eventEmitter).onContentSizeChange([self _textInputMetrics]);
}
}