Skip to content

Commit

Permalink
fixed (iOS) setState is not working properly for text inline image #…
Browse files Browse the repository at this point in the history
…41236 (#41287)

Summary:
Closes #41236

`setState` is not working properly for text inline image

## Fixed demo (please see the animation as in rendering pass rather than re-mounting pass)

https://github.com/facebook/react-native/assets/149237137/d4b894bf-2283-4963-8dc7-b8f5a9f81315

## How it works

**Background**

Inline views are not included in the Yoga node tree, rather, they are retained as attachments of `NSAttributedString` and are managed by the respective text fragment (`RCTTextShadowView`) that includes them (Code snippet 1).

```
<div layout="width: 393; height: 852; top: 0; left: 0;" style="" >
  <div layout="width: 393; height: 852; top: 0; left: 0;" style="flex: 1; " >
    <div layout="width: 393; height: 852; top: 0; left: 0;" style="flex: 1; " >
      <div layout="width: 393; height: 241; top: 0; left: 0;" style="padding-top: 59px; " >
        <div layout="width: 393; height: 50; top: 59; left: 0;" style="width: 100%; height: 50px; " >
          <div layout="width: 393; height: 17.3333; top: 0; left: 0;" style="" has-custom-measure="true"></div>
        </div>
        <div layout="width: 393; height: 50; top: 109; left: 0;" style="width: 100%; height: 50px; " >
          <div layout="width: 393; height: 17.3333; top: 0; left: 0;" style="" has-custom-measure="true"></div>
        </div>
        /* Text node that does not contain inline view that is supposed to be there */
        <div layout="width: 393; height: 74.3333; top: 167; left: 0;" style="margin-top: 8px; " has-custom-measure="true"></div>
      </div>
    </div>
  </div>
</div>
```
**Code snippet 1, output of  YGNodePrint() in _normal layout_ flow**

The layout of such node is handled ad-hoc (_inline layout_) inside `RCTTextShadowView` (Code snippet 2)

```
/* Inline node is calculated on its own */
<div layout="width: 48; height: 48; top: 0; left: 0;" style="overflow: hidden; width: 48px; height: 48px; min-width: 0px; min-height: 0px; " ></div>
```
**Code snippet 2, output of  YGNodePrint() in _inline layout_ flow**

**Problem description**

The issue happens when the sizes given by `setState()` are smaller than those in the last round `setState()`. Since the `min-width` and `min-height` are already populated (Code snippet 3) with greater values, the new layout pass gives rather a `noop`.

```
/* min sizes are greater than them in the new style */
<div layout="width: 48; height: 48; top: 0; left: 0;" style="overflow: hidden; width: 32px; height: 32px; min-width: 48px; min-height: 48px; " ></div>
```

**Code snippet 3, output of  YGNodePrint() in _inline layout (issue)_ flow**

**Fix description**

This biased `min-width` and `min-height` are given using the **current frame size** (i.e., sizes set in the last round `setState()`) in the _inline layout_ (in `RCTTextShadowView` § Background), whilst the same parameters are given as ~~CGSizeZero~~ `_minimumSize` in _normal layout_ (§ Background).

The change of this PR is to unify this behavior of _normal layout_ by using ~~CGSizeZero~~ `_minimumSize` as the input also for _inline layout_.

## Changelog:

[IOS] [FIXED] - `setState` is not working properly for text inline image

Pull Request resolved: #41287

Test Plan:
- Using **rn-tester** for basic verification
- Complete plan: https://docs.google.com/spreadsheets/d/1QLuqNvqX0dM4K68ygRoHDR3S0wcK5umptmjoR7KtkaY/edit?usp=sharing

Reviewed By: cipolleschi

Differential Revision: D50967547

Pulled By: NickGerleman

fbshipit-source-id: b3b6d6919fd9d3302977dc771a41c22f7b796ba5
  • Loading branch information
ehsemloh authored and facebook-github-bot committed Nov 4, 2023
1 parent 2a9caec commit 36ef646
Showing 1 changed file with 1 addition and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ - (void)layoutSubviewsWithContext:(RCTLayoutContext)layoutContext
localLayoutContext.absolutePosition.x += frame.origin.x;
localLayoutContext.absolutePosition.y += frame.origin.y;

[shadowView layoutWithMinimumSize:frame.size
[shadowView layoutWithMinimumSize:{shadowView.minWidth.value, shadowView.minHeight.value}
maximumSize:frame.size
layoutDirection:self.layoutMetrics.layoutDirection
layoutContext:localLayoutContext];
Expand Down

0 comments on commit 36ef646

Please sign in to comment.