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
Usa placeholders descriptivos para guiar al usuario
Agrupa estados relacionados en un objeto
Implementa validación en tiempo real
Usa keyboardType apropiado para cada campo
Considera accesibilidad con labels claros
Optimiza rendimiento con useCallback para handlers
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
🎬 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
Publicar un comentario