Text
Text in React Native: the Text primitive, styling, nesting, accessibility, and the rules that make typography behave the same on iOS and Android.
React Native — Text
EXAMPLE
import React from 'react';
import { Text, View, StyleSheet, Platform } from 'react-native';
export default function ProfileCard({ user }) {
return (
<View style={styles.card}>
{/* ===== 1. Basic Text ===== */}
<Text style={styles.name}>{user.name}</Text>
{/* ===== 2. Nesting and inheritance =====
Text inherits text style props from PARENT Text only. Wrapping
mixed children in a single <Text> lets you compose runs cleanly. */}
<Text style={styles.body}>
<Text style={styles.bold}>Joined</Text> in{' '}
<Text style={styles.italic}>April 2024</Text>.
</Text>
{/* ===== 3. Truncation =====
numberOfLines + ellipsizeMode are the cross-platform combo. */}
<Text style={styles.bio} numberOfLines={2} ellipsizeMode="tail">
{user.bio}
</Text>
{/* ===== 4. Accessibility =====
Screen readers expect a single utterance per Text block. */}
<Text accessibilityRole="header" accessibilityLevel={2} style={styles.section}>
Recent activity
</Text>
{/* ===== 5. Selectable text (long-press to copy) ===== */}
<Text selectable style={styles.body}>{user.email}</Text>
{/* ===== 6. Press handler on text ===== */}
<Text style={styles.link} onPress={() => onOpen(user.profileUrl)}>
View full profile
</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
padding: 16,
backgroundColor: 'white',
borderRadius: 12,
gap: 8,
},
name: {
fontSize: 20,
fontWeight: '600',
color: '#0f172a',
// RN uses string weights; iOS handles all, Android needs a font that supports the weight
},
body: { fontSize: 14, color: '#334155', lineHeight: 20 },
bold: { fontWeight: '700' },
italic: { fontStyle: 'italic' },
bio: { fontSize: 13, color: '#475569' },
section: { fontSize: 16, fontWeight: '600', marginTop: 12 },
link: {
color: '#2563eb',
textDecorationLine: 'underline',
// textDecorationLine works on iOS; on Android underline needs a parent Text
},
});
// ===== 7. Loading a custom font (Expo) =====
// Install: npx expo install expo-font @expo/vector-icons
// import { useFonts } from 'expo-font';
// const [loaded] = useFonts({ 'Inter-Bold': require('./assets/Inter-Bold.ttf') });
// Then: style={{ fontFamily: 'Inter-Bold' }}
// ===== 8. Platform-specific overrides =====
const headerFont = Platform.select({
ios: 'SFProDisplay-Bold',
android: 'Roboto',
default: 'System',
});
// ===== Patterns to internalise =====
// - Text ONLY accepts text and other Text children. Strings outside Text crash.
// - Use a single <Text> with nested <Text> children for typographic runs
// - numberOfLines + ellipsizeMode = portable truncation
// - selectable on emails/codes for long-press copy
// - allowFontScaling={false} only when you must; respect user accessibility text sizes
// ===== Pitfalls =====
// - Putting plain strings inside <View>: 'Text strings must be rendered within a <Text>'
// - Inline styles in a hot list -> creates a new style object every render; use StyleSheet
// - textDecorationLine: 'underline' on a parent View has no effect; needs a Text
// - fontWeight: '600' on Android without a font that ships the cut -> displays Regular
// - numberOfLines with flexShrink mishandled -> ellipsis cuts at wrong width
Why it matters
Text is the only primitive that renders text — and the only one that can contain text. Compose nested Text for typographic runs, lean on numberOfLines + ellipsizeMode for portability, and pay attention to fontWeight differences across platforms. These small reflexes are what separate "looks fine" from "ships clean".
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
import { Text } from 'react-native';
<Text style={{ fontSize: 18, fontWeight: '600' }}>
Hello {name}
</Text>
Try it Yourself »
Discussion
Loading…