Form Handling & Validation
Learn to implement form validation, error handling, and form state management in React Native applications. This is a foundational concept in cross-platform mobile development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world React Native experience. Take your time with each section and practice the examples
Form State Management
Use React hooks like useState and useReducer to manage form state. Consider using libraries like Formik or React Hook Form for complex forms with validation.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Validation Strategies
- Real-time validation - Validate as user types — a critical concept in cross-platform mobile development that you will use frequently in real projects
- On-submit validation - Validate when form is submitted
- Field-level validation - Validate individual fields
- Form-level validation - Validate entire form — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Custom validation rules - Business logic validation
Error Handling Patterns
- Display error messages below input fields — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Highlight invalid fields with red borders — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Show success states for valid inputs — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Prevent form submission with invalid data — a critical concept in cross-platform mobile development that you will use frequently in real projects
- Provide clear error messages to users — a critical concept in cross-platform mobile development that you will use frequently in real projects
Form Validation Example
import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert } from 'react-native';
const ValidatedForm = () => {
const [formData, setFormData] = useState({
email: '',
password: '',
confirmPassword: '',
});
const [errors, setErrors] = useState({});
const validateEmail = (email: string) => {
const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;
return emailRegex.test(email);
};
const validatePassword = (password: string) => {
return password.length >= 8;
};
const validateForm = () => {
const newErrors = {};
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!validateEmail(formData.email)) {
newErrors.email = 'Please enter a valid email';
}
if (!formData.password) {
newErrors.password = 'Password is required';
} else if (!validatePassword(formData.password)) {
newErrors.password = 'Password must be at least 8 characters';
}
if (formData.password !== formData.confirmPassword) {
newErrors.confirmPassword = 'Passwords do not match';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({
...prev,
[field]: value
}));
// Clear error when user starts typing
if (errors[field]) {
setErrors(prev => ({
...prev,
[field]: ''
}));
}
};
const handleSubmit = () => {
if (validateForm()) {
Alert.alert('Success', 'Form is valid!');
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>Validated Form</Text>
<View style={styles.inputContainer}>
<Text style={styles.label}>Email</Text>
<TextInput
style={[styles.input, errors.email && styles.inputError]}
value={formData.email}
onChangeText={(value) => handleInputChange('email', value)}
placeholder="Enter your email"
keyboardType="email-address"
autoCapitalize="none"
/>
{errors.email && <Text style={styles.errorText}>{errors.email}</Text>}
</View>
<View style={styles.inputContainer}>
<Text style={styles.label}>Password</Text>
<TextInput
style={[styles.input, errors.password && styles.inputError]}
value={formData.password}
onChangeText={(value) => handleInputChange('password', value)}
placeholder="Enter your password"
secureTextEntry
/>
{errors.password && <Text style={styles.errorText}>{errors.password}</Text>}
</View>
<View style={styles.inputContainer}>
<Text style={styles.label}>Confirm Password</Text>
<TextInput
style={[styles.input, errors.confirmPassword && styles.inputError]}
value={formData.confirmPassword}
onChangeText={(value) => handleInputChange('confirmPassword', value)}
placeholder="Confirm your password"
secureTextEntry
/>
{errors.confirmPassword && <Text style={styles.errorText}>{errors.confirmPassword}</Text>}
</View>
<TouchableOpacity style={styles.button} onPress={handleSubmit}>
<Text style={styles.buttonText}>Submit</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 30,
color: '#333',
},
inputContainer: {
marginBottom: 20,
},
label: {
fontSize: 16,
fontWeight: '500',
marginBottom: 8,
color: '#333',
},
input: {
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: 'white',
},
inputError: {
borderColor: '#f44336',
},
errorText: {
color: '#f44336',
fontSize: 14,
marginTop: 4,
},
button: {
backgroundColor: '#2196F3',
padding: 15,
borderRadius: 8,
alignItems: 'center',
marginTop: 20,
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
});
export default ValidatedForm;