discussions-and-proposals icon indicating copy to clipboard operation
discussions-and-proposals copied to clipboard

Please export `textAncestor` context

Open AlanSl opened this issue 3 years ago • 1 comments

Introduction

In React Native, everything inside a first <Text> component behaves differently to everything outside (further <Text> elements apply annotations rather than defining a container, loose strings are allowed as children, Views are positioned as nested views and some layout styles no longer take effect, rules around focusability and the application of accessibility props changes, etc etc).

Internally, React Native uses textAncestor context to find out if there is a <Text> further up the tree and to judge if this contextual flip has taken place.

There are some cases where it would be extremely useful for library authors and app developers to also be able to access this context, and see if a component is being rendered inside or outside of <Text>.

Details

Block-level Text and inline nested Text behave very differently; and inline nested Views also behave somewhat differently. There are several cases where it would be useful for a component author to be able to do const isNested = useContext(textAncestor) and make choices based on how their component's top level children are being rendered.

Here are a few example cases I've encountered where this would have been very useful:

  • Removing, replacing or tweaking style properties and accessibility props that behave differently or are not supported when nested.
  • Warning devs of inappropriate usage (e.g. if a textual component should not be used nested because it is not possible to make it sufficiently accessible).
  • Making components that accept string children and wrap them in <Text> only when necessary, simplifying styling.
  • Working around longstanding bugs such as accessibility issues on accessing nested links and layout issues on nested Views.

Discussion points

I can't see any negatives to exporting textAncestor context. Its API is incredibly simple so in theory should be very stable: its value is true if there's a <Text> up the tree, false if not. I understand that many internal utilities are best kept private so their evolution doesn't get held back by the need to minimise breaking changes to public APIs but textAncestor is so simple, this doesn't seem to be an issue.

I accept that many of the uses of textAncestor are not common, but also, they are the sorts of uses that can't be worked around any other way currently.

AlanSl avatar Jul 28 '22 10:07 AlanSl

This issue was mention several time in the conversation 2022: How can we improve React Native?

  • Text wrapping around images. https://stackoverflow.com/questions/69216957/wrapping-multiple-lines-of-text-around-inline-image (comment)
  • Measure function (positions) of nested Text component returns 0 or undefined always, and not working And you should use View inside text (comment)

Similar issues have been reported in react-native. Text on Android is represented with TextView, while nested Texts are represented as spans (Images as TextInlineImageSpan).

The style prop does not apply to nested Text. A solution to this issue is supporting the style prop for Nested Text on Android. The issue has also been reported here. I will work on landing a series of PRs that add this functionality to react-native. The PRs will close following react-native issues (if you have an open issues in react-native, feel free to comment it here):

fabOnReact avatar Dec 22 '22 16:12 fabOnReact