Master React Native TextInput - Complete Guide
Last update: 2025-04-24The TextInput component is a fundamental building block for collecting user input in React Native applications. Whether you’re building forms, search bars, or chat interfaces, understanding TextInput is crucial. In this guide, you’ll learn how to implement and customize TextInput with practical examples.
Basic TextInput Usage
Let’s start with a simple example:
import React, { useState } from 'react';
import { View, TextInput, StyleSheet } from 'react-native';
const BasicTextInput = () => {
const [text, setText] = useState('');
return (
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={setText}
value={text}
placeholder="Enter text here"
placeholderTextColor="#666"
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 20
},
input: {
height: 40,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 10,
backgroundColor: '#fff'
}
});
export default BasicTextInput;
This example demonstrates:
- Basic input field setup with state management
- Simple styling with borders and padding
- Placeholder text with custom color
- Controlled component pattern with
value
andonChangeText
Input Types and Keyboard Configuration
TextInput can be configured for different types of input:
import React, { useState } from 'react';
import { View, TextInput, StyleSheet } from 'react-native';
const InputTypes = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [phone, setPhone] = useState('');
return (
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={setEmail}
value={email}
placeholder="Email"
keyboardType="email-address"
autoCapitalize="none"
autoComplete="email"
/>
<TextInput
style={styles.input}
onChangeText={setPassword}
value={password}
placeholder="Password"
secureTextEntry
autoCapitalize="none"
/>
<TextInput
style={styles.input}
onChangeText={setPhone}
value={phone}
placeholder="Phone"
keyboardType="phone-pad"
autoComplete="tel"
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 20,
gap: 10
},
input: {
height: 40,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 10,
backgroundColor: '#fff'
}
});
export default InputTypes;
Key features demonstrated:
- Email input with appropriate keyboard type
- Password input with secure text entry
- Phone number input with numeric keyboard
- Auto-capitalization and auto-complete settings
Advanced Styling and Validation
Here’s an example with more advanced styling and basic validation:
import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet } from 'react-native';
const AdvancedInput = () => {
const [username, setUsername] = useState('');
const [error, setError] = useState('');
const [isFocused, setIsFocused] = useState(false);
const validateUsername = (text: string) => {
setUsername(text);
if (text.length < 3) {
setError('Username must be at least 3 characters');
} else if (!/^[a-zA-Z0-9]+$/.test(text)) {
setError('Username can only contain letters and numbers');
} else {
setError('');
}
};
return (
<View style={styles.container}>
<Text style={styles.label}>Username</Text>
<TextInput
style={[styles.input, isFocused && styles.focused, error && styles.error]}
onChangeText={validateUsername}
value={username}
placeholder="Enter username"
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
{error ? <Text style={styles.errorText}>{error}</Text> : null}
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 20
},
label: {
fontSize: 16,
marginBottom: 8,
color: '#333',
fontWeight: '500'
},
input: {
height: 40,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 10,
backgroundColor: '#fff'
},
focused: {
borderColor: '#007AFF',
shadowColor: '#007AFF',
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.2,
shadowRadius: 5
},
error: {
borderColor: '#FF3B30'
},
errorText: {
color: '#FF3B30',
fontSize: 12,
marginTop: 4
}
});
export default AdvancedInput;
This example showcases:
- Custom styling for focus and error states
- Real-time input validation
- Error message display
- Shadow effects on focus
- Input labels
Multiline Input and Character Count
For longer text input with character counting:
import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet } from 'react-native';
const MultilineInput = () => {
const [text, setText] = useState('');
const maxLength = 200;
return (
<View style={styles.container}>
<TextInput
style={styles.multilineInput}
onChangeText={setText}
value={text}
placeholder="Write your message here..."
multiline
numberOfLines={4}
maxLength={maxLength}
textAlignVertical="top"
/>
<Text style={styles.counter}>
{text.length}/{maxLength} characters
</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 20
},
multilineInput: {
height: 100,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
paddingHorizontal: 10,
paddingTop: 10,
backgroundColor: '#fff',
fontSize: 16
},
counter: {
alignSelf: 'flex-end',
color: '#666',
fontSize: 12,
marginTop: 4
}
});
export default MultilineInput;
Features demonstrated:
- Multiline input configuration
- Character limit with counter
- Proper text alignment for multiline input
- Flexible height handling
Search Input with Clear Button
A common pattern for search functionality:
import React, { useState } from 'react';
import { View, TextInput, TouchableOpacity, StyleSheet } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
const SearchInput = () => {
const [search, setSearch] = useState('');
const clearSearch = () => {
setSearch('');
};
return (
<View style={styles.container}>
<View style={styles.searchContainer}>
<Ionicons name="search" size={20} color="#666" style={styles.searchIcon} />
<TextInput
style={styles.searchInput}
onChangeText={setSearch}
value={search}
placeholder="Search..."
clearButtonMode="while-editing" // iOS only
/>
{search.length > 0 && (
<TouchableOpacity onPress={clearSearch}>
<Ionicons name="close-circle" size={20} color="#666" />
</TouchableOpacity>
)}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 20
},
searchContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f0f0',
borderRadius: 8,
paddingHorizontal: 10
},
searchIcon: {
marginRight: 10
},
searchInput: {
flex: 1,
height: 40,
fontSize: 16
}
});
export default SearchInput;
This search input demonstrates:
- Icon integration with Expo vector icons
- Clear button functionality
- Platform-specific features (clearButtonMode for iOS)
- Styled search container with icons
Best Practices
Input Validation
- Validate input in real-time when appropriate
- Provide clear feedback for errors
- Consider using a validation library for complex forms
User Experience
- Use appropriate keyboard types
- Implement auto-capitalization rules
- Add clear buttons for easy text clearing
- Show/hide password toggles
Performance
- Debounce search input if making API calls
- Use controlled components consistently
- Handle keyboard events properly
Styling
- Maintain consistent styling across your app
- Consider platform differences
- Implement proper focus and error states
- Use appropriate padding and spacing
Common Use Cases
- Login/Registration forms
- Search bars
- Chat input fields
- Comment sections
- Profile editing
- Settings forms
Summary
React Native’s TextInput component is versatile and can be customized for various use cases. By following these patterns and best practices, you can create polished and user-friendly input experiences in your apps.
Key takeaways:
- Choose appropriate input types and keyboard configurations
- Implement proper validation and error handling
- Style inputs consistently with your app’s theme
- Consider platform-specific features
- Follow accessibility guidelines
Now you’re ready to implement professional text inputs in your React Native apps! 🚀