0Pricing
React Native Academy · บทเรียน

พื้นฐาน TextInput และประเภทแป้นพิมพ์

แสดง TextInput เชื่อมเข้ากับสถานะด้วย onChangeText กำหนดประเภทแป้นพิมพ์สำหรับข้อมูลอีเมลหรือตัวเลข และจัดการเหตุการณ์ปุ่ม Return

พื้นฐาน TextInput และประเภทแป้นพิมพ์ เป็นบทเรียน React Native Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Native Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน

บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ

The TextInput Component

TextInput is the React Native component for capturing keyboard input from users. It renders as a native text field on both iOS and Android, giving users the platform's native typing experience including autocorrect, predictive text, and system keyboard shortcuts. Import it from react-native and use it for any input that requires a keyboard: search boxes, login forms, settings fields, and chat message composers. Without styling, TextInput has no visible border on iOS — always style it to make it visible to users.

import { TextInput, View, StyleSheet } from 'react-native';
import { useState } from 'react';

export default function BasicInput() {
  const [text, setText] = useState('');

  return (
    <View style={{ padding: 16 }}>
      <TextInput
        value={text}
        onChangeText={setText}
        placeholder='Type something here...'
        style={styles.input}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 10,
    paddingHorizontal: 14,
    paddingVertical: 12,
    fontSize: 16,
    backgroundColor: '#fff',
  },
});

onChangeText vs onChange

The onChangeText callback is the most common way to react to text input. It receives the new text string directly as its argument, making it easy to pass to a useState setter: onChangeText={setText}. The lower-level onChange callback receives a full event object (event.nativeEvent.text) — useful when you also need other event metadata like cursor position. For most use cases, onChangeText is simpler and preferred. Use onChange only when you need the native event details.

import { TextInput } from 'react-native';
import { useState } from 'react';

function TextInputExample() {
  const [text, setText] = useState('');

  return (
    <>
      {/* Simple: receives the string directly */}
      <TextInput
        onChangeText={(newText) => setText(newText)}
        // shorthand equivalent:
        // onChangeText={setText}
      />

      {/* Advanced: receives the full event object */}
      <TextInput
        onChange={(event) => {
          console.log('text:', event.nativeEvent.text);
          console.log('selection:', event.nativeEvent.selection);
        }}
      />
    </>
  );
}

Keyboard Types for Different Input

The keyboardType prop controls which keyboard variant the OS displays. For a numeric input, 'numeric' shows a numpad. For emails, 'email-address' includes the @ and . keys prominently. 'phone-pad' shows the phone dialer layout. 'decimal-pad' is like numeric but includes a decimal point. 'url' shows / and .com shortcuts. Using the correct keyboard type is a usability win — it reduces the keystrokes needed to enter data and prevents users from typing invalid characters.

import { View, TextInput, Text, StyleSheet } from 'react-native';

export default function KeyboardTypesDemo() {
  return (
    <View style={{ padding: 16, gap: 12 }}>
      <TextInput style={styles.input} keyboardType='default' placeholder='Default text' />
      <TextInput style={styles.input} keyboardType='email-address' placeholder='email@example.com' />
      <TextInput style={styles.input} keyboardType='numeric' placeholder='Enter a number' />
      <TextInput style={styles.input} keyboardType='phone-pad' placeholder='Phone number' />
      <TextInput style={styles.input} keyboardType='decimal-pad' placeholder='Price (0.00)' />
      <TextInput style={styles.input} keyboardType='url' placeholder='https://...' />
    </View>
  );
}

const styles = StyleSheet.create({
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, fontSize: 16, backgroundColor: '#fff' },
});

Secure Text Entry for Passwords

For password fields, set secureTextEntry={true} to hide the typed characters with bullet points. This is essential for any field containing sensitive data — passwords, PINs, security codes. You can add a show/hide password toggle by managing a showPassword boolean in state and toggling secureTextEntry. Also set autoCapitalize='none' and autoCorrect={false} on password fields — you don't want autocorrect or capital letters changing a user's password as they type.

import { TextInput, TouchableOpacity, Text, View, StyleSheet } from 'react-native';
import { useState } from 'react';

export default function PasswordInput() {
  const [password, setPassword] = useState('');
  const [visible, setVisible] = useState(false);

  return (
    <View style={styles.wrapper}>
      <TextInput
        value={password}
        onChangeText={setPassword}
        secureTextEntry={!visible}
        autoCapitalize='none'
        autoCorrect={false}
        placeholder='Password'
        style={styles.input}
      />
      <TouchableOpacity
        style={styles.toggle}
        onPress={() => setVisible(v => !v)}
      >
        <Text style={{ fontSize: 18 }}>{visible ? '🙈' : '👁'}</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  wrapper: { flexDirection: 'row', alignItems: 'center', borderWidth: 1, borderColor: '#ccc', borderRadius: 10, paddingHorizontal: 14 },
  input: { flex: 1, paddingVertical: 12, fontSize: 16 },
  toggle: { paddingLeft: 8 },
});

autoCapitalize and autoCorrect

autoCapitalize controls when the OS capitalizes the first letter. Values: 'none' (never capitalize), 'sentences' (first letter of each sentence, default), 'words' (first letter of each word), 'characters' (every character). Use 'none' for usernames, email addresses, and passwords. Use 'words' for name fields. autoCorrect={false} disables autocorrect entirely, which is essential for usernames, technical terms, or any field where the user knows what they're typing.

import { View, TextInput, StyleSheet } from 'react-native';

export default function FormInputs() {
  return (
    <View style={{ padding: 16, gap: 12 }}>
      {/* Name: capitalize each word, allow autocorrect */}
      <TextInput
        style={styles.input}
        placeholder='Full name'
        autoCapitalize='words'
        autoCorrect={true}
      />
      {/* Username: no caps, no autocorrect */}
      <TextInput
        style={styles.input}
        placeholder='@username'
        autoCapitalize='none'
        autoCorrect={false}
      />
      {/* Email: no caps, no autocorrect */}
      <TextInput
        style={styles.input}
        placeholder='Email address'
        keyboardType='email-address'
        autoCapitalize='none'
        autoCorrect={false}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, fontSize: 16 },
});

returnKeyType and onSubmitEditing

The returnKeyType prop changes the label on the keyboard's Return key: 'done', 'go', 'next', 'search', 'send'. Use 'next' to indicate that pressing Return moves to the next field. The onSubmitEditing callback fires when the user presses the Return key. Combine returnKeyType='next' with onSubmitEditing to programmatically focus the next TextInput using a ref — this creates a smooth, tab-like navigation between form fields that users expect on mobile.

import { View, TextInput, StyleSheet, useRef } from 'react-native';

export default function MultiFieldForm() {
  const emailRef = useRef(null);
  const passwordRef = useRef(null);

  return (
    <View style={{ padding: 16, gap: 12 }}>
      <TextInput
        ref={emailRef}
        style={styles.input}
        placeholder='Email'
        keyboardType='email-address'
        returnKeyType='next'
        onSubmitEditing={() => passwordRef.current?.focus()}
      />
      <TextInput
        ref={passwordRef}
        style={styles.input}
        placeholder='Password'
        secureTextEntry
        returnKeyType='done'
        onSubmitEditing={() => console.log('Form submitted!')}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, fontSize: 16 },
});

Multiline TextInput

For multi-line text like a bio, message, or comment, add the multiline prop. The TextInput will expand as the user types new lines and support newline characters. Use numberOfLines on Android to set the initial height (iOS auto-sizes). The textAlignVertical: 'top' style (Android only) prevents text from starting at the vertical center of the input box. On iOS, multiline inputs grow to fit their content automatically when there's no explicit height set. Combine maxLength with a character counter display for message composer fields.

import { TextInput, Text, View, StyleSheet } from 'react-native';
import { useState } from 'react';

export default function BioInput() {
  const [bio, setBio] = useState('');
  const MAX_LENGTH = 200;

  return (
    <View style={{ padding: 16 }}>
      <TextInput
        value={bio}
        onChangeText={setBio}
        placeholder='Tell us about yourself...'
        multiline
        numberOfLines={4}     // Android: initial height
        maxLength={MAX_LENGTH}
        style={styles.input}
        textAlignVertical='top' // Android: align text to top
      />
      <Text style={styles.counter}>
        {bio.length}/{MAX_LENGTH}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 10, padding: 12, fontSize: 15, minHeight: 100 },
  counter: { textAlign: 'right', color: '#999', fontSize: 12, marginTop: 4 },
});

Focus, Blur, and onFocus / onBlur Events

TextInput fires onFocus when the user taps into it (keyboard appears) and onBlur when they tap away (keyboard hides). Use these to show/hide helper text, change the border color to indicate active state, or trigger field-level validation. A common pattern is to validate a field only after the user has left it (on blur), not while they are still typing — this avoids showing error messages before the user finishes typing. Track which field is focused with a state variable if you need to style multiple inputs differently based on focus.

import { TextInput, View, StyleSheet } from 'react-native';
import { useState } from 'react';

export default function FocusableInput({ placeholder, onBlurValidate }) {
  const [focused, setFocused] = useState(false);
  const [value, setValue] = useState('');
  const [error, setError] = useState('');

  function handleBlur() {
    setFocused(false);
    const err = onBlurValidate ? onBlurValidate(value) : '';
    setError(err);
  }

  return (
    <View>
      <TextInput
        value={value}
        onChangeText={setValue}
        onFocus={() => setFocused(true)}
        onBlur={handleBlur}
        placeholder={placeholder}
        style={[
          styles.input,
          focused && styles.focused,
          error && styles.error,
        ]}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  input: { borderWidth: 1.5, borderColor: '#ddd', borderRadius: 10, padding: 12, fontSize: 16 },
  focused: { borderColor: '#4f86f7', shadowColor: '#4f86f7', shadowOpacity: 0.2, shadowRadius: 4, shadowOffset: { width: 0, height: 2 } },
  error: { borderColor: '#e74c3c' },
});

Dismissing the Keyboard

On mobile, the keyboard doesn't dismiss automatically when users tap outside a TextInput. Use Keyboard.dismiss() from react-native to programmatically hide it. Wrap your screen content in a TouchableWithoutFeedback that calls Keyboard.dismiss() on press, so tapping anywhere outside the keyboard dismisses it. Alternatively, use the keyboardDismissMode prop on ScrollView: 'on-drag' dismisses the keyboard when the user starts scrolling, which is a comfortable mobile UX pattern.

import { TouchableWithoutFeedback, Keyboard, ScrollView, TextInput, StyleSheet, View } from 'react-native';

export default function DismissibleForm() {
  return (
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <ScrollView
        style={{ flex: 1 }}
        keyboardDismissMode='on-drag'  // dismiss on scroll
        keyboardShouldPersistTaps='handled'
      >
        <View style={{ padding: 16, gap: 12 }}>
          <TextInput style={styles.input} placeholder='Name' />
          <TextInput style={styles.input} placeholder='Email' keyboardType='email-address' />
          <TextInput style={styles.input} placeholder='Message' multiline numberOfLines={4} textAlignVertical='top' />
        </View>
      </ScrollView>
    </TouchableWithoutFeedback>
  );
}

const styles = StyleSheet.create({
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, fontSize: 16 },
});

KeyboardAvoidingView

When the keyboard appears, it covers the bottom of the screen and can hide text inputs in forms. Wrap your screen in KeyboardAvoidingView to automatically push the content up when the keyboard opens. Set behavior='padding' on iOS and behavior='height' on Android (use Platform.OS to pick the right value). Pair it with keyboardVerticalOffset to account for the header height. For screens with many inputs, combining KeyboardAvoidingView with a ScrollView inside provides the best experience.

import { KeyboardAvoidingView, Platform, ScrollView, TextInput, TouchableOpacity, Text, StyleSheet } from 'react-native';

export default function LoginScreen() {
  return (
    <KeyboardAvoidingView
      style={{ flex: 1 }}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      keyboardVerticalOffset={60} // adjust for header height
    >
      <ScrollView contentContainerStyle={styles.form}>
        <TextInput style={styles.input} placeholder='Email' keyboardType='email-address' />
        <TextInput style={styles.input} placeholder='Password' secureTextEntry />
        <TouchableOpacity style={styles.btn}>
          <Text style={styles.btnText}>Log In</Text>
        </TouchableOpacity>
      </ScrollView>
    </KeyboardAvoidingView>
  );
}

const styles = StyleSheet.create({
  form: { padding: 24, gap: 16, flexGrow: 1, justifyContent: 'center' },
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 10, padding: 14, fontSize: 16 },
  btn: { backgroundColor: '#4f86f7', padding: 16, borderRadius: 10, alignItems: 'center' },
  btnText: { color: '#fff', fontWeight: 'bold', fontSize: 16 },
});

Input Masking for Formatted Values

Some inputs need formatted display as the user types — credit card numbers with spaces every 4 digits, phone numbers with dashes, or dates in DD/MM/YYYY format. Implement this in the onChangeText handler: strip formatting characters from the raw input, apply the format, and set the formatted string as state. The TextInput shows the formatted value (from state), but you store the raw digits separately for submission. Libraries like react-native-mask-input provide a drop-in masked TextInput that handles common patterns automatically.

import { TextInput } from 'react-native';
import { useState } from 'react';

// Manual phone number formatting: (555) 123-4567
export default function PhoneInput({ onPhoneChange }) {
  const [display, setDisplay] = useState('');

  function formatPhone(raw) {
    const digits = raw.replace(/\D/g, '').slice(0, 10); // digits only, max 10
    let formatted = digits;
    if (digits.length > 6) {
      formatted = '(' + digits.slice(0,3) + ') ' + digits.slice(3,6) + '-' + digits.slice(6);
    } else if (digits.length > 3) {
      formatted = '(' + digits.slice(0,3) + ') ' + digits.slice(3);
    } else if (digits.length > 0) {
      formatted = '(' + digits;
    }
    setDisplay(formatted);
    onPhoneChange(digits); // pass raw digits to parent
  }

  return (
    <TextInput
      value={display}
      onChangeText={formatPhone}
      keyboardType='phone-pad'
      placeholder='(555) 123-4567'
      style={{ borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, fontSize: 16 }}
    />
  );
}

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: keyboardType shows the appropriate keyboard for the data type, returnKeyType with refs enables tab-like navigation between form fields, and KeyboardAvoidingView prevents the keyboard from covering input fields at the bottom of the screen. Next up we explore adding tap feedback with TouchableOpacity and Pressable.

คำถามที่พบบ่อย

บทเรียน “พื้นฐาน TextInput และประเภทแป้นพิมพ์” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “พื้นฐาน TextInput และประเภทแป้นพิมพ์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Native Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “พื้นฐาน TextInput และประเภทแป้นพิมพ์”

แสดง TextInput เชื่อมเข้ากับสถานะด้วย onChangeText กำหนดประเภทแป้นพิมพ์สำหรับข้อมูลอีเมลหรือตัวเลข และจัดการเหตุการณ์ปุ่ม Return คุณปฏิบัติ React Native Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Native Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Native Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “พื้นฐาน TextInput และประเภทแป้นพิมพ์” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน React Native Academy นี้ได้ไหม

ได้ บทเรียน React Native Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน TextInput และประเภทแป้นพิมพ์
  2. ตัวจัดการการแตะด้วย TouchableOpacity และ Pressable
  3. ตัวสลับ สวิตช์ และช่องทำเครื่องหมาย
  4. การสร้างแบบฟอร์มเข้าสู่ระบบอย่างง่าย
← กลับไปที่ React Native Academy