Inconsistent text wrap behavior with flexbox #1730
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Report
Issues and Steps to Reproduce
Snack Repro: https://snack.expo.dev/@meata/text-bug?platform=ios
Select the iOS preview.
The gist is this: I have a horizontal stack with two text fields, when the first field gets too long I expect it to wrap and take the minimum width it can. This doesn't seem to be the case, worse, it seems to behave differently depending on the number of letters in the first field. The first section shows the behavior I expect, the second is the weird behavior. With both the total width is the same, only difference is the additional letter.
Same issue can be observed on Android but the text needs to be changed a bit to make it work.
On web it at least seems consistent, even though I'm not sure why it does not shrink.
Expected Behavior
Explained above, but generally I expect it to at least behave consistently (either shrink or don't)
Actual Behavior
Explained above, adding a single character changes the layout from shrinking to not shrinking.
Link to Code
https://snack.expo.dev/@meata/text-bug?platform=ios
There are a couple of related things here:
@kzlar is there any way you could repro this against RN new arch (default in RN 0.76/Expo 52)? It goes through different measurement path.
For #2, there's a good chance on Android that we aren't filling bounds of multiline text ala web in this logic
94fdc38822/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java (L661)
Problem:
The first text is already too long that it wraps in 2 lines, making the width enough => It won't shrink
The second text will initially fit in one line but since the items exceed the parent width => it will shrink. The calculated width after shrinking is correct but that new width can no longer hold that text in one line, thus it wraps.
In the second text, after the text shrinks the new layout width is calculated with mode
Exactly
(SizingMode::StretchFit
)Solution
If the child shrank, use mode
AtMost
(SizingMode::FitContent
)Oh wah, thanks @s77rt! I had also looked into @kzlar issue and did not understand why the first text was fitting it's container; now it's clear! It's actually not affected by
flexShrink=1
as it's already wrapping in regard to its full parent's width.Second text is actually the standard, using the
Exactly
mode as you said.Regarding your solution, would'nt it be a big breaking change if we start using
AtMost
for shrinking children?@delphinebugner Since we are using less width than what we have allocated we may have unfilled space (even with
flexGrow
). Now I can't get the yellow rectangle to take the remaining space.@s77rt when I looked at behavior on web, sizing explicitly to fit-content, wrapped paragraph took full available width instead of width of max line. So, when we shrink, we only shrink to amount of space needed to also add inflexible child.
Ie in top example, yellow inflexible child should hug the right.
So I think measure function logic in RN needs to be changed to return available width when text is wrapped, instead of longest line width.
Separately, Yoga should be calculating initial flex basis as max content instead of fit-content, but that’s a gnarlier bug.
Ah I got it. It does make sense in a way and it's consistent with web. Will look into this one then
Appreciate the prompt help on this folks :)
@s77rt Hi appreciate the effort on making the behaviour more consistent, but is it possible to make it an option for the other way around where the wrapped paragraph took the width of max line instead of full available width as we have a use case in our application for this behaviour? Thanks
@weihanyau I don't think that something that may land upstream. You can try either path RN or make use of
onTextLayout
@s77rt Thanks for the response. May I know what is "path RN"? Can't seem to find anything related to it
@weihanyau I'm assuming you are facing this on react native which you can find the PR on https://github.com/facebook/react-native/pull/47435.
Sorry a typo, I meant to patch reactnative, you can use patch-package to revert the above PR changes