14. Componente Text Input

 

Tutorial: Componente TextInput en React Native

📱 Parte 14: Componente TextInput - Capturando Entradas del Usuario

🎯 Objetivo:

Aprender a usar el componente TextInput para capturar datos del usuario, manejar estados, aplicar estilos y crear formularios interactivos en React Native.


📸 Analizando los Ejemplos de las Imágenes

Imagen 1: TextInput Básico

javascript

import React from 'react';

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


const App = () => {

  const handleChange = (valor) => {

    console.log(valor);  // ✅ Capturando el valor

  };

  

  return (

    <ScrollView>

      <TextInput

        style={{

          borderWidth: 1,      // ✅ Borde visible

          borderRadius: 20,    // ✅ Bordes redondeados

          marginHorizontal: 20,

          marginVertical: 10,

        }}

        onChangeText={(valor) => handleChange(valor)} // ✅ Evento de cambio

      />

    </ScrollView>

  );

};

Imagen 2: TextInput con Estado

javascript

import React, { useState } from 'react';  // ✅ Importando useState

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


const App = () => {

  const [texto, setTexto] = useState('');  // ✅ Estado para el texto

  

  const handleChange = (valor) => {

    setTexto(valor);  // ✅ Actualizando estado

    console.log(valor);

  };

  

  return (

    <ScrollView>

      <TextInput

        style={styles.input}

        onChangeText={(valor) => handleChange(valor)}

      />

      <Text>{texto}</Text>  {/* ✅ Mostrando el texto capturado */}

    </ScrollView>

  );

};


🚀 Paso 1: ¿Qué es TextInput?

TextInput es el componente para capturar texto del usuario, equivalente a <input> o <textarea> en HTML. Permite crear campos de texto, formularios y entradas de datos.

1.1 Importación Básica

javascript

import React from 'react';

import { TextInput } from 'react-native'; // ¡IMPORTANTE importar!


📝 Paso 2: TextInput Básico

2.1 TextInput Más Simple

javascript

const InputBasico = () => {

  return (

    <View style={styles.container}>

      <TextInput />

    </View>

  );

};

Resultado visual:

text

┌─────────────────────────────────┐

│                                 │

│    [    ]   ← ¡Solo el cursor!  │

│                                 │

└─────────────────────────────────┘

2.2 DEMOSTRACIÓN: Con y Sin Estilos

javascript

const ComparacionInput = () => {

  return (

    <View style={styles.container}>

      {/* Input sin estilos (invisible) */}

      <Text style={styles.label}>Sin estilos:</Text>

      <TextInput />

      

      {/* Input con borde básico */}

      <Text style={styles.label}>Con borde básico:</Text>

      <TextInput style={{ borderWidth: 1 }} />

      

      {/* Input con estilos completos */}

      <Text style={styles.label}>Con estilos completos:</Text>

      <TextInput 

        style={{

          borderWidth: 1,

          borderRadius: 8,

          padding: 10,

          fontSize: 16,

          backgroundColor: '#fff',

        }}

        placeholder="Escribe algo aquí..."

      />

    </View>

  );

};


const styles = StyleSheet.create({

  container: {

    flex: 1,

    padding: 20,

  },

  label: {

    marginTop: 20,

    marginBottom: 5,

    fontSize: 16,

    color: '#666',

  },

});


🎨 Paso 3: Estilizando TextInput

3.1 Propiedades de Estilo Principales

javascript

<TextInput

  style={{

    // BORDES

    borderWidth: 1,              // Grosor del borde

    borderColor: '#ccc',         // Color del borde

    borderRadius: 8,             // Bordes redondeados

    borderBottomWidth: 2,        // Solo borde inferior

    

    // TEXTO

    fontSize: 16,                // Tamaño del texto

    color: '#333',               // Color del texto

    fontWeight: 'normal',        // Peso de la fuente

    textAlign: 'left',           // Alineación

    

    // FONDO Y ESPACIADO

    backgroundColor: '#fff',     // Color de fondo

    padding: 12,                 // Relleno interno

    margin: 10,                  // Margen externo

    

    // SOMBRA (iOS)

    shadowColor: '#000',

    shadowOffset: { width: 0, height: 2 },

    shadowOpacity: 0.1,

    shadowRadius: 4,

    

    // ELEVACIÓN (Android)

    elevation: 2,

    

    // DIMENSIONES

    height: 50,                  // Altura fija

    width: '100%',               // Ancho completo

  }}

/>

3.2 Ejemplo: Diferentes Tipos de Inputs

javascript

const TiposDeInputs = () => {

  return (

    <ScrollView style={styles.container}>

      {/* Input básico */}

      <Text style={styles.tituloSeccion}>Input Básico</Text>

      <TextInput 

        style={styles.inputBasico}

        placeholder="Nombre completo"

      />

      

      {/* Input con icono (simulado) */}

      <Text style={styles.tituloSeccion}>Input con Búsqueda</Text>

      <TextInput 

        style={styles.inputBusqueda}

        placeholder="🔍 Buscar productos..."

      />

      

      {/* Input de contraseña */}

      <Text style={styles.tituloSeccion}>Input de Contraseña</Text>

      <TextInput 

        style={styles.inputNormal}

        placeholder="Contraseña"

        secureTextEntry={true}      // Oculta el texto

      />

      

      {/* Input de correo */}

      <Text style={styles.tituloSeccion}>Input de Email</Text>

      <TextInput 

        style={styles.inputNormal}

        placeholder="correo@ejemplo.com"

        keyboardType="email-address"  // Teclado especializado

        autoCapitalize="none"

      />

      

      {/* Input numérico */}

      <Text style={styles.tituloSeccion}>Input Numérico</Text>

      <TextInput 

        style={styles.inputNormal}

        placeholder="Edad"

        keyboardType="numeric"

      />

      

      {/* Input multilínea */}

      <Text style={styles.tituloSeccion}>TextArea (Multilínea)</Text>

      <TextInput 

        style={styles.textArea}

        placeholder="Escribe tu mensaje aquí..."

        multiline={true}

        numberOfLines={4}

      />

    </ScrollView>

  );

};


const styles = StyleSheet.create({

  container: {

    flex: 1,

    padding: 20,

    backgroundColor: '#f5f5f5',

  },

  tituloSeccion: {

    fontSize: 18,

    fontWeight: '600',

    marginTop: 25,

    marginBottom: 10,

    color: '#333',

  },

  inputBasico: {

    borderWidth: 1,

    borderColor: '#ddd',

    borderRadius: 8,

    padding: 12,

    fontSize: 16,

    backgroundColor: '#fff',

  },

  inputBusqueda: {

    borderWidth: 1,

    borderColor: '#ddd',

    borderRadius: 25,

    padding: 12,

    fontSize: 16,

    backgroundColor: '#fff',

    paddingLeft: 45,

  },

  inputNormal: {

    borderWidth: 1,

    borderColor: '#ddd',

    borderRadius: 8,

    padding: 12,

    fontSize: 16,

    backgroundColor: '#fff',

  },

  textArea: {

    borderWidth: 1,

    borderColor: '#ddd',

    borderRadius: 8,

    padding: 12,

    fontSize: 16,

    backgroundColor: '#fff',

    height: 100,

    textAlignVertical: 'top',

  },

});


🔄 Paso 4: Capturando Datos con Estado

4.1 Manejo Básico de Estado

javascript

import React, { useState } from 'react';


const InputConEstado = () => {

  const [texto, setTexto] = useState('');  // Estado inicial vacío

  

  return (

    <View style={styles.container}>

      {/* Input que actualiza el estado */}

      <TextInput

        style={styles.input}

        value={texto}  // Valor controlado por estado

        onChangeText={setTexto}  // Actualiza estado directamente

        placeholder="Escribe algo..."

      />

      

      {/* Mostrando el valor actual */}

      <View style={styles.preview}>

        <Text style={styles.previewLabel}>Texto ingresado:</Text>

        <Text style={styles.previewText}>

          {texto || '(vacío)'}

        </Text>

        <Text style={styles.previewCount}>

          Caracteres: {texto.length}

        </Text>

      </View>

      

      {/* Botón para limpiar */}

      <TouchableOpacity 

        style={styles.boton}

        onPress={() => setTexto('')}

      >

        <Text style={styles.botonTexto}>Limpiar</Text>

      </TouchableOpacity>

    </View>

  );

};

4.2 Múltiples Inputs con Estado

javascript

const FormularioCompleto = () => {

  // Estados para cada campo

  const [nombre, setNombre] = useState('');

  const [email, setEmail] = useState('');

  const [telefono, setTelefono] = useState('');

  const [mensaje, setMensaje] = useState('');

  

  const handleEnviar = () => {

    const datos = { nombre, email, telefono, mensaje };

    console.log('Datos del formulario:', datos);

    alert('Formulario enviado correctamente');

  };

  

  return (

    <ScrollView style={styles.container}>

      <Text style={styles.titulo}>Formulario de Contacto</Text>

      

      {/* Campo Nombre */}

      <Text style={styles.label}>Nombre completo *</Text>

      <TextInput

        style={styles.input}

        value={nombre}

        onChangeText={setNombre}

        placeholder="Ej: Juan Pérez"

      />

      

      {/* Campo Email */}

      <Text style={styles.label}>Correo electrónico *</Text>

      <TextInput

        style={styles.input}

        value={email}

        onChangeText={setEmail}

        placeholder="correo@ejemplo.com"

        keyboardType="email-address"

        autoCapitalize="none"

      />

      

      {/* Campo Teléfono */}

      <Text style={styles.label}>Teléfono</Text>

      <TextInput

        style={styles.input}

        value={telefono}

        onChangeText={setTelefono}

        placeholder="+1 234 567 890"

        keyboardType="phone-pad"

      />

      

      {/* Campo Mensaje */}

      <Text style={styles.label}>Mensaje *</Text>

      <TextInput

        style={[styles.input, styles.textArea]}

        value={mensaje}

        onChangeText={setMensaje}

        placeholder="Escribe tu mensaje aquí..."

        multiline={true}

        numberOfLines={4}

      />

      

      {/* Resumen en tiempo real */}

      <View style={styles.resumen}>

        <Text style={styles.resumenTitulo}>Resumen:</Text>

        <Text>Nombre: {nombre || '(sin nombre)'}</Text>

        <Text>Email: {email || '(sin email)'}</Text>

        <Text>Teléfono: {telefono || '(sin teléfono)'}</Text>

        <Text>Caracteres mensaje: {mensaje.length}</Text>

      </View>

      

      {/* Botón de enviar */}

      <TouchableOpacity 

        style={styles.botonEnviar}

        onPress={handleEnviar}

      >

        <Text style={styles.botonEnviarTexto}>Enviar Formulario</Text>

      </TouchableOpacity>

    </ScrollView>

  );

};


🎯 Paso 5: Propiedades Clave de TextInput

5.1 Propiedades de Comportamiento

javascript

<TextInput

  // VALOR Y EVENTOS

  value={texto}                      // Valor controlado

  defaultValue="Valor inicial"       // Valor inicial no controlado

  onChangeText={(texto) => {}}       // Cuando cambia el texto

  onFocus={() => {}}                 // Cuando recibe foco

  onBlur={() => {}}                  // Cuando pierde foco

  onSubmitEditing={() => {}}         // Al presionar "enter"

  

  // CONFIGURACIÓN DE TECLADO

  keyboardType="default"             // 'default', 'email-address', 'numeric', 'phone-pad', etc.

  autoCapitalize="sentences"         // 'none', 'sentences', 'words', 'characters'

  autoCorrect={true}                 // Corrección automática

  autoCompleteType="off"             // Autocompletado

  secureTextEntry={false}            // Para contraseñas

  

  // APARIENCIA

  placeholder="Texto de ejemplo"     // Texto guía

  placeholderTextColor="#999"        // Color del placeholder

  editable={true}                    // Si se puede editar

  selectTextOnFocus={false}          // Seleccionar texto al enfocar

  

  // MULTILÍNEA

  multiline={false}                  // Textarea

  numberOfLines={1}                  // Líneas (multiline=true)

  textAlignVertical="top"            // Para multilínea

  

  // OTROS

  maxLength={100}                    // Máximo de caracteres

  returnKeyType="done"               // Texto en tecla return

  blurOnSubmit={true}                // Perder foco al enviar

  clearButtonMode="while-editing"    // iOS: botón para limpiar

/>

5.2 Ejemplo: Formulario de Login con Validación

javascript

const LoginForm = () => {

  const [email, setEmail] = useState('');

  const [password, setPassword] = useState('');

  const [errors, setErrors] = useState({});

  

  const validateEmail = (email) => {

    const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    return re.test(email);

  };

  

  const handleLogin = () => {

    const newErrors = {};

    

    if (!email) {

      newErrors.email = 'El email es requerido';

    } else if (!validateEmail(email)) {

      newErrors.email = 'Email no válido';

    }

    

    if (!password) {

      newErrors.password = 'La contraseña es requerida';

    } else if (password.length < 6) {

      newErrors.password = 'Mínimo 6 caracteres';

    }

    

    if (Object.keys(newErrors).length === 0) {

      console.log('Login exitoso:', { email, password });

      alert('¡Inicio de sesión exitoso!');

    } else {

      setErrors(newErrors);

    }

  };

  

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Iniciar Sesión</Text>

      

      {/* Email Input */}

      <Text style={styles.label}>Email</Text>

      <TextInput

        style={[

          styles.input,

          errors.email && styles.inputError

        ]}

        value={email}

        onChangeText={(text) => {

          setEmail(text);

          if (errors.email) setErrors({...errors, email: ''});

        }}

        placeholder="usuario@ejemplo.com"

        keyboardType="email-address"

        autoCapitalize="none"

        autoCorrect={false}

      />

      {errors.email && (

        <Text style={styles.errorText}>{errors.email}</Text>

      )}

      

      {/* Password Input */}

      <Text style={styles.label}>Contraseña</Text>

      <TextInput

        style={[

          styles.input,

          errors.password && styles.inputError

        ]}

        value={password}

        onChangeText={(text) => {

          setPassword(text);

          if (errors.password) setErrors({...errors, password: ''});

        }}

        placeholder="••••••••"

        secureTextEntry={true}

      />

      {errors.password && (

        <Text style={styles.errorText}>{errors.password}</Text>

      )}

      

      {/* Login Button */}

      <TouchableOpacity 

        style={styles.loginButton}

        onPress={handleLogin}

      >

        <Text style={styles.loginButtonText}>Ingresar</Text>

      </TouchableOpacity>

    </View>

  );

};


const styles = StyleSheet.create({

  container: {

    flex: 1,

    padding: 30,

    justifyContent: 'center',

    backgroundColor: '#fff',

  },

  titulo: {

    fontSize: 28,

    fontWeight: 'bold',

    marginBottom: 30,

    textAlign: 'center',

    color: '#333',

  },

  label: {

    fontSize: 16,

    marginBottom: 8,

    color: '#555',

  },

  input: {

    borderWidth: 1,

    borderColor: '#ddd',

    borderRadius: 8,

    padding: 12,

    fontSize: 16,

    marginBottom: 5,

    backgroundColor: '#f9f9f9',

  },

  inputError: {

    borderColor: '#ff3b30',

    backgroundColor: '#fff5f5',

  },

  errorText: {

    color: '#ff3b30',

    fontSize: 14,

    marginBottom: 15,

  },

  loginButton: {

    backgroundColor: '#007AFF',

    borderRadius: 8,

    padding: 15,

    alignItems: 'center',

    marginTop: 20,

  },

  loginButtonText: {

    color: '#fff',

    fontSize: 18,

    fontWeight: '600',

  },

});


⚡ Paso 6: Referencias y Enfoque Programático

6.1 Usando useRef para Controlar Focus

javascript

import React, { useRef } from 'react';


const InputConRef = () => {

  const inputRef = useRef(null);

  const segundoInputRef = useRef(null);

  

  const handleFocusNext = () => {

    segundoInputRef.current.focus();

  };

  

  return (

    <View style={styles.container}>

      {/* Primer Input */}

      <TextInput

        ref={inputRef}

        style={styles.input}

        placeholder="Primer campo"

        returnKeyType="next"

        onSubmitEditing={handleFocusNext}  // Al presionar "next"

      />

      

      {/* Segundo Input */}

      <TextInput

        ref={segundoInputRef}

        style={styles.input}

        placeholder="Segundo campo"

        returnKeyType="done"

      />

      

      {/* Botón para focus manual */}

      <TouchableOpacity 

        style={styles.boton}

        onPress={() => inputRef.current.focus()}

      >

        <Text>Enfocar primer input</Text>

      </TouchableOpacity>

    </View>

  );

};

6.2 Ejemplo Avanzado: Búsqueda en Tiempo Real

javascript

const BusquedaAvanzada = () => {

  const [busqueda, setBusqueda] = useState('');

  const [resultados, setResultados] = useState([]);

  const inputRef = useRef(null);

  

  const productos = [

    'iPhone 14 Pro Max',

    'MacBook Pro M2',

    'iPad Air',

    'Apple Watch Series 8',

    'AirPods Pro',

    'iMac 24"',

    'Mac mini',

  ];

  

  const handleBusqueda = (texto) => {

    setBusqueda(texto);

    

    if (texto.trim() === '') {

      setResultados([]);

    } else {

      const filtrados = productos.filter(producto =>

        producto.toLowerCase().includes(texto.toLowerCase())

      );

      setResultados(filtrados);

    }

  };

  

  return (

    <View style={styles.container}>

      {/* Input de búsqueda */}

      <View style={styles.buscadorContainer}>

        <TextInput

          ref={inputRef}

          style={styles.buscadorInput}

          value={busqueda}

          onChangeText={handleBusqueda}

          placeholder="🔍 Buscar productos Apple..."

          clearButtonMode="while-editing"

          returnKeyType="search"

        />

        <TouchableOpacity 

          style={styles.botonLimpiar}

          onPress={() => {

            setBusqueda('');

            setResultados([]);

          }}

        >

          <Text></Text>

        </TouchableOpacity>

      </View>

      

      {/* Resultados de búsqueda */}

      <ScrollView style={styles.resultadosContainer}>

        {resultados.map((producto, index) => (

          <TouchableOpacity 

            key={index}

            style={styles.resultadoItem}

            onPress={() => {

              setBusqueda(producto);

              inputRef.current.blur();

            }}

          >

            <Text style={styles.resultadoTexto}>{producto}</Text>

          </TouchableOpacity>

        ))}

        

        {busqueda && resultados.length === 0 && (

          <Text style={styles.sinResultados}>

            No se encontraron productos para "{busqueda}"

          </Text>

        )}

      </ScrollView>

      

      {/* Estadísticas */}

      <View style={styles.estadisticas}>

        <Text>Búsqueda: "{busqueda || '(vacía)'}"</Text>

        <Text>Resultados: {resultados.length}</Text>

        <Text>Caracteres: {busqueda.length}</Text>

      </View>

    </View>

  );

};


🛠️ Paso 7: Ejercicio Práctico - Formulario de Registro

Objetivo: Crear un formulario de registro completo con validación

javascript

const RegistroUsuario = () => {

  // Estados para cada campo

  const [formData, setFormData] = useState({

    nombre: '',

    email: '',

    telefono: '',

    password: '',

    confirmPassword: '',

  });

  

  const [errors, setErrors] = useState({});

  const [mostrarPassword, setMostrarPassword] = useState(false);

  

  // Manejar cambios en cualquier campo

  const handleChange = (campo, valor) => {

    setFormData(prev => ({ ...prev, [campo]: valor }));

    

    // Limpiar error del campo modificado

    if (errors[campo]) {

      setErrors(prev => ({ ...prev, [campo]: '' }));

    }

  };

  

  const validarFormulario = () => {

    const nuevosErrores = {};

    

    // Validar nombre

    if (!formData.nombre.trim()) {

      nuevosErrores.nombre = 'El nombre es requerido';

    }

    

    // Validar email

    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (!formData.email) {

      nuevosErrores.email = 'El email es requerido';

    } else if (!emailRegex.test(formData.email)) {

      nuevosErrores.email = 'Email no válido';

    }

    

    // Validar teléfono

    const telefonoRegex = /^[0-9]{10}$/;

    if (formData.telefono && !telefonoRegex.test(formData.telefono)) {

      nuevosErrores.telefono = 'Teléfono debe tener 10 dígitos';

    }

    

    // Validar contraseña

    if (!formData.password) {

      nuevosErrores.password = 'La contraseña es requerida';

    } else if (formData.password.length < 6) {

      nuevosErrores.password = 'Mínimo 6 caracteres';

    }

    

    // Validar confirmación

    if (formData.password !== formData.confirmPassword) {

      nuevosErrores.confirmPassword = 'Las contraseñas no coinciden';

    }

    

    return nuevosErrores;

  };

  

  const handleRegistro = () => {

    const erroresValidacion = validarFormulario();

    

    if (Object.keys(erroresValidacion).length === 0) {

      console.log('Datos válidos:', formData);

      alert('¡Registro exitoso!');

      // Aquí enviarías los datos al servidor

    } else {

      setErrors(erroresValidacion);

    }

  };

  

  return (

    <ScrollView style={styles.container}>

      <Text style={styles.titulo}>Crear Cuenta</Text>

      

      {/* Campo Nombre */}

      <Text style={styles.label}>Nombre completo *</Text>

      <TextInput

        style={[styles.input, errors.nombre && styles.inputError]}

        value={formData.nombre}

        onChangeText={(text) => handleChange('nombre', text)}

        placeholder="Juan Pérez"

      />

      {errors.nombre && <Text style={styles.error}>{errors.nombre}</Text>}

      

      {/* Campo Email */}

      <Text style={styles.label}>Email *</Text>

      <TextInput

        style={[styles.input, errors.email && styles.inputError]}

        value={formData.email}

        onChangeText={(text) => handleChange('email', text)}

        placeholder="correo@ejemplo.com"

        keyboardType="email-address"

        autoCapitalize="none"

        autoCorrect={false}

      />

      {errors.email && <Text style={styles.error}>{errors.email}</Text>}

      

      {/* Campo Teléfono */}

      <Text style={styles.label}>Teléfono</Text>

      <TextInput

        style={[styles.input, errors.telefono && styles.inputError]}

        value={formData.telefono}

        onChangeText={(text) => handleChange('telefono', text)}

        placeholder="1234567890"

        keyboardType="phone-pad"

        maxLength={10}

      />

      {errors.telefono && <Text style={styles.error}>{errors.telefono}</Text>}

      

      {/* Campo Contraseña */}

      <Text style={styles.label}>Contraseña *</Text>

      <View style={styles.passwordContainer}>

        <TextInput

          style={[styles.input, styles.passwordInput, errors.password && styles.inputError]}

          value={formData.password}

          onChangeText={(text) => handleChange('password', text)}

          placeholder="••••••••"

          secureTextEntry={!mostrarPassword}

        />

        <TouchableOpacity

          style={styles.showPasswordButton}

          onPress={() => setMostrarPassword(!mostrarPassword)}

        >

          <Text>{mostrarPassword ? '👁️' : '👁️‍🗨️'}</Text>

        </TouchableOpacity>

      </View>

      {errors.password && <Text style={styles.error}>{errors.password}</Text>}

      

      {/* Confirmar Contraseña */}

      <Text style={styles.label}>Confirmar Contraseña *</Text>

      <TextInput

        style={[styles.input, errors.confirmPassword && styles.inputError]}

        value={formData.confirmPassword}

        onChangeText={(text) => handleChange('confirmPassword', text)}

        placeholder="••••••••"

        secureTextEntry={!mostrarPassword}

      />

      {errors.confirmPassword && (

        <Text style={styles.error}>{errors.confirmPassword}</Text>

      )}

      

      {/* Previsualización */}

      <View style={styles.preview}>

        <Text style={styles.previewTitle}>Datos ingresados:</Text>

        <Text>Nombre: {formData.nombre || '(vacío)'}</Text>

        <Text>Email: {formData.email || '(vacío)'}</Text>

        <Text>Teléfono: {formData.telefono || '(vacío)'}</Text>

        <Text>Contraseña: {'•'.repeat(formData.password.length)}</Text>

      </View>

      

      {/* Botón de registro */}

      <TouchableOpacity 

        style={styles.registerButton}

        onPress={handleRegistro}

      >

        <Text style={styles.registerButtonText}>Registrarse</Text>

      </TouchableOpacity>

    </ScrollView>

  );

};


⚠️ Paso 8: Errores Comunes y Soluciones

❌ Error: "TextInput no se muestra"

javascript

// ❌ MAL: Falta estilo

<TextInput />


// ✅ BIEN: Agregar borde o fondo

<TextInput style={{ borderWidth: 1, padding: 10 }} />

❌ Error: "No se captura el texto"

javascript

// ❌ MAL: Falta onChangeText

<TextInput value={texto} />


// ✅ BIEN: Agregar manejador de cambios

<TextInput value={texto} onChangeText={setTexto} />

❌ Error: "Teclado no se cierra"

javascript

// SOLUCIÓN: Usar Keyboard.dismiss()

import { Keyboard } from 'react-native';


<TouchableOpacity onPress={() => Keyboard.dismiss()}>

  <Text>Cerrar teclado</Text>

</TouchableOpacity>

❌ Error: "Inputs muy juntos en iOS"

javascript

// SOLUCIÓN: Usar KeyboardAvoidingView

import { KeyboardAvoidingView, Platform } from 'react-native';


<KeyboardAvoidingView

  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}

  style={{ flex: 1 }}

>

  {/* Tus TextInputs aquí */}

</KeyboardAvoidingView>


📋 Paso 9: Mejores Prácticas con TextInput

9.1 Consejos Profesionales

  1. Usa placeholders descriptivos para guiar al usuario

  2. Agrupa estados relacionados en un objeto

  3. Implementa validación en tiempo real

  4. Usa keyboardType apropiado para cada campo

  5. Considera accesibilidad con labels claros

  6. Optimiza rendimiento con useCallback para handlers

  7. Proporciona feedback visual durante la validación

9.2 Plantilla de Input Reutilizable

javascript

const CustomInput = ({

  label,

  value,

  onChangeText,

  placeholder,

  error,

  secureTextEntry,

  keyboardType,

  autoCapitalize,

  multiline,

}) => {

  return (

    <View style={styles.inputContainer}>

      {label && <Text style={styles.inputLabel}>{label}</Text>}

      <TextInput

        style={[

          styles.input,

          multiline && styles.inputMultiline,

          error && styles.inputError,

        ]}

        value={value}

        onChangeText={onChangeText}

        placeholder={placeholder}

        secureTextEntry={secureTextEntry}

        keyboardType={keyboardType}

        autoCapitalize={autoCapitalize}

        multiline={multiline}

        textAlignVertical={multiline ? 'top' : 'center'}

      />

      {error && <Text style={styles.errorText}>{error}</Text>}

    </View>

  );

};


// Uso

<CustomInput

  label="Email"

  value={email}

  onChangeText={setEmail}

  placeholder="correo@ejemplo.com"

  error={errors.email}

  keyboardType="email-address"

/>


🎯 Resumen: Tipos Comunes de TextInput

Tipo

Propiedades clave

Uso común

Texto simple

keyboardType="default"

Nombres, direcciones

Email

keyboardType="email-address", autoCapitalize="none"

Correos electrónicos

Número

keyboardType="numeric"

Edad, cantidad, precios

Teléfono

keyboardType="phone-pad"

Números telefónicos

Contraseña

secureTextEntry={true}

Contraseñas, PINs

Búsqueda

returnKeyType="search", clearButtonMode

Campos de búsqueda

Multilínea

multiline={true}, textAlignVertical="top"

Comentarios, mensajes


🎬 Próximo Tutorial

En el siguiente video aprenderemos:

  • Componente Button para acciones del usuario

  • Diferentes tipos de botones

  • Estilización de botones personalizados

  • Manejo de eventos de clic


✅ ¡Ahora dominas el componente TextInput! Es fundamental para cualquier aplicación que requiera interacción del usuario. Practica creando diferentes tipos de formularios y validaciones para convertirte en un experto


Comentarios

Entradas más populares de este blog

18. Visualizar nuestros componentes limpios con StyleSheet

15. Componente Image

Tema: 23. Justify Content en Flexbox para Column (Columna) en React Nativ