Text component
The library offers two ways of integrating into your app:
-
PlainTextis a high-performance, single-style text component. You use it directly at the call sites where it fits. This gives the best performance: no per-render check, no fallback branch, and no chance of silently landing on RN<Text>. -
Textis a drop-in replacement for RN<Text>. It automatically rendersPlainTextfor simple strings and falls back to RN<Text>for nested ones. Swap the import and get most of Plain Text's performance benefits across the app without touching any call sites.
Reach for Text where an existing call site takes arbitrary <Text> children you
don't control, or as a first pass before switching individual call sites to
PlainText. See Should you use it? for the underlying
tradeoff. The rest of this page covers Text.
How it works
In outline, Text does this (simplified, without the development warnings
described below):
The real implementation,
src/Text.tsx,
makes the same decision but is tuned for speed: it checks for a plain string
first and renders the native view directly, skipping the PlainText wrapper.
Text renders PlainText only when all of these hold:
deoptisn't set (see below).- The content is text: the
textprop if set, otherwisechildren. That's a string, a number (orbigint), or a mix like{count} items(which JSX passes as[count, ' items']). Anything containing an element (nested<Text>, an icon), no children at all, or a lone boolean ({flag && label}withflagfalse) falls back to RN<Text>. - It isn't itself nested inside another
<Text>— RN'sunstable_TextAncestorContextistruefor descendants of a<Text>, andPlainTextdoesn't support nested<Text>composition. Falling back keeps that nesting working.
Whichever branch is taken, all other props are forwarded unchanged, so Text is
API-compatible with RN <Text>. When it resolves to PlainText, only the props and
styles PlainText supports apply.
Props are never inspected to pick a branch, so release builds pay nothing for them.
Instead, in development Text warns once per prop when it renders PlainText with a
prop PlainText can't reproduce: onPress, onLongPress, onPressIn, onPressOut,
onTextLayout, selectable, adjustsFontSizeToFit, dataDetectorType, or
dynamicTypeRamp. Add deopt to those instances.
The reverse applies on fallback: RN <Text> drops the PlainText-only props
hyphens, lang, unstable_lineHeightClippingCompat and the
fontVariationSettings style, so development builds warn once when a fallback
(automatic or via deopt) drops one of them. The text prop isn't dropped: it's
passed to RN <Text> as children.
Deoptimizing a single instance
children shape and text nesting are handled automatically — you don't need deopt
for those. It's for a single-style string that would otherwise take the PlainText
path, but relies on a prop PlainText doesn't support (such as onPress, see the
development warning above) or hits a PlainText rendering issue. Pass deopt to
skip the selection for that instance and always render RN <Text>:
deopt itself is never forwarded to RN <Text>. An explicit deopt={false} reaches
the native PlainText view as an ignored prop, since stripping it would cost every
render. Omit deopt rather than setting it to false.
Using it in your own Text component
You don't need to add a separate Text import: an existing centralized Text component,
such as a design system's, can make the same decision. The simplest way is to render
this library's Text in place of RN <Text>:
To own the RN <Text> fallback yourself, use unstable_mapTextProps, the same function
Text runs. It returns the native props when PlainText can render, or null when
deopt is set or the content isn't plain text. Props PlainText can't reproduce, such
as onPress, don't make it return null: they only warn in development, so pass
deopt for those. It doesn't check nesting, so do that first. Like
unstable_NativePlainText, which renders its result, its props aren't guaranteed
stable across releases:
This renders the NativePlainText view directly, as Text does, skipping the
PlainText JS wrapper. unstable_mapTextProps gives the same development warnings
for props PlainText ignores. The warnings for PlainText-only props dropped on
fallback stay in Text, and so does passing the text prop to RN <Text> as
children.