iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

TextInput

TextInput is the cross-platform input. Controlled by state; supports keyboard types, autocapitalisation, multiline, ref-based focus — and many platform-specific gotchas.

Controlled, validation, refs, keyboard

EXAMPLE
import { useState, useRef } from 'react';
import {
    TextInput,
    View,
    Text,
    Pressable,
    Platform,
    StyleSheet,
    Keyboard,
    KeyboardAvoidingView,
    ScrollView,
} from 'react-native';

// 1) Basic controlled input
function Email() {
    const [email, setEmail] = useState('');
    return (
        <TextInput
            value={email}
            onChangeText={setEmail}
            placeholder="you@example.com"
            placeholderTextColor="#999"
            keyboardType="email-address"
            autoCapitalize="none"
            autoCorrect={false}
            autoComplete="email"
            textContentType="emailAddress"          // iOS
            inputMode="email"
            style={styles.input}
        />
    );
}

// 2) Password — secureTextEntry + show/hide
function Password() {
    const [pw, setPw] = useState('');
    const [show, setShow] = useState(false);
    return (
        <View style={styles.row}>
            <TextInput
                value={pw}
                onChangeText={setPw}
                placeholder="Password"
                secureTextEntry={!show}
                autoCapitalize="none"
                autoComplete="password"
                textContentType="password"
                style={[styles.input, { flex: 1 }]}
            />
            <Pressable onPress={() => setShow(s => !s)} style={styles.iconBtn}>
                <Text>{show ? '🙈' : '👁'}</Text>
            </Pressable>
        </View>
    );
}

// 3) Multiline (textarea)
<TextInput
    multiline
    numberOfLines={4}
    style={[styles.input, { textAlignVertical: 'top', minHeight: 96 }]}
    placeholder="Comments…"
/>

// 4) Numeric input — typed amount
function Amount() {
    const [val, setVal] = useState('');
    const onChange = (t) => {
        // Allow digits + one dot
        const clean = t.replace(/[^0-9.]/g, '').replace(/^(\d*\.\d{0,2}).*$/, '$1');
        setVal(clean);
    };
    return (
        <TextInput
            value={val}
            onChangeText={onChange}
            keyboardType="decimal-pad"
            placeholder="0.00"
            style={styles.input}
        />
    );
}

// 5) Refs — focus / blur / clear
function Login() {
    const emailRef = useRef(null);
    const pwRef    = useRef(null);
    return (
        <View>
            <TextInput
                ref={emailRef}
                returnKeyType="next"
                onSubmitEditing={() => pwRef.current?.focus()}
                placeholder="Email"
                style={styles.input}
            />
            <TextInput
                ref={pwRef}
                returnKeyType="go"
                onSubmitEditing={() => submit()}
                secureTextEntry
                placeholder="Password"
                style={styles.input}
            />
        </View>
    );
}

// 6) Validation — inline error display
function Form() {
    const [email, setEmail] = useState('');
    const [touched, setTouched] = useState(false);
    const error = touched && !/\S+@\S+\.\S+/.test(email) ? 'Invalid email' : '';
    return (
        <View>
            <TextInput
                value={email}
                onChangeText={setEmail}
                onBlur={() => setTouched(true)}
                style={[styles.input, !!error && styles.inputError]}
            />
            {!!error && <Text style={styles.errorText}>{error}</Text>}
        </View>
    );
}

// 7) KeyboardAvoidingView — push inputs above the keyboard
<KeyboardAvoidingView
    behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
    style={{ flex: 1 }}
>
    <ScrollView keyboardShouldPersistTaps="handled">
        {/* form fields */}
    </ScrollView>
</KeyboardAvoidingView>

// 8) Dismiss keyboard on tap-outside
import { TouchableWithoutFeedback } from 'react-native';
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
    <View style={{ flex: 1 }}>{/* … */}</View>
</TouchableWithoutFeedback>

// 9) Auto-focus on mount
useEffect(() => { emailRef.current?.focus(); }, []);

// 10) Caret + selection
<TextInput
    selection={{ start: 5, end: 10 }}
    onSelectionChange={(e) => console.log(e.nativeEvent.selection)}
/>

// 11) Useful prop reference
// - value / onChangeText           — controlled binding
// - placeholder / placeholderTextColor
// - keyboardType / inputMode       — 'default' | 'email-address' | 'numeric' | 'decimal-pad' | 'number-pad' | 'phone-pad' | 'url'
// - autoCapitalize                 — 'none' | 'sentences' | 'words' | 'characters'
// - autoCorrect / spellCheck       — booleans
// - autoComplete                   — 'email' | 'password' | 'username' | 'tel' | 'name' | etc.
// - textContentType                — iOS-specific OS-level suggestions
// - secureTextEntry                — password mode
// - multiline / numberOfLines
// - returnKeyType                  — 'done' | 'next' | 'go' | 'search' | 'send'
// - blurOnSubmit
// - editable                       — disabled state
// - maxLength
// - selectTextOnFocus

const styles = StyleSheet.create({
    row:      { flexDirection: 'row', alignItems: 'center', gap: 8 },
    input:    { borderWidth: 1, borderColor: '#cbd5e1', borderRadius: 8, padding: 12, fontSize: 16, marginBottom: 12 },
    inputError:{ borderColor: '#ef4444' },
    errorText:{ color: '#ef4444', fontSize: 13, marginTop: -8, marginBottom: 12 },
    iconBtn:  { padding: 8 },
});

Why it matters

Match the keyboard to the input: keyboardType=\"email-address\" + autoCapitalize=\"none\" + autoComplete=\"email\". Users notice when the wrong keyboard pops up; OS-level autofill notices the missing hints.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import { TextInput } from 'react-native';
const [name, setName] = useState('');
<TextInput
    value={name}
    onChangeText={setName}
    placeholder="Your name"
    style={{ borderWidth: 1, padding: 8 }}
/>
Try it Yourself »

Discussion

Loading…