Introduction
- Forms are everywhere—from onboarding flows and account setup to user profiles and settings screens. In this post, you’ll learn how to build form inputs in React Native using `TextInput`, manage their state with `useState`, and avoid repetitive styling by using reusable components.
- We’ll walk through the process of building a Create User form with Name, Email, and Bio fields, covering essential techniques and best practices along the way.
Name Input Setup
NameInput.tsx
import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export default function NameInput() {
const [name, setName] = useState('');
return (
<View style={styles.container}>
{/* Label for the input */}
<Text style={styles.label}>Name</Text>
{/* Controlled TextInput that updates local state */}
<TextInput
style={styles.input}
value={name}
onChangeText={setName}
placeholder="Enter your name"
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
marginBottom: 16
},
label: {
fontWeight: 'bold', // Makes the label bold
fontSize: 16, // Increases font size for readability
marginBottom: 8 // Adds space between label and input
},
input: {
padding: 10, // Adds space inside the input
borderWidth: 1, // Thin border around the input
borderColor: '#ccc',// Light gray border
borderRadius: 6 // Slightly rounded corners
}
});
- Let’s imagine we’re building an onboarding screen that asks the user for their name. This input will capture that first piece of personal info and store it using local state.
- We'll use a simple `TextInput` component and keep things clean with a `StyleSheet`. The `label` will be bold, and the input box will be clearly styled for readability.
Email Input Props
EmailInput.tsx
import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export default function EmailInput() {
const [email, setEmail] = useState('');
return (
<View style={styles.container}>
<Text style={styles.label}>Email</Text>
<TextInput
style={styles.input}
value={email}
onChangeText={setEmail}
placeholder="you@example.com"
keyboardType="email-address" // brings up the email keyboard on mobile
autoCorrect={false} // turns off autocorrect
autoCapitalize="none" // avoids auto-capitalizing email addresses
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
marginBottom: 16
},
label: {
fontWeight: 'bold',
fontSize: 16,
marginBottom: 8
},
input: {
padding: 10,
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 6
}
});
- The email input is similar to the name input but includes props to improve the user experience—like turning off autocorrect and using an email-friendly keyboard layout.
- This is especially useful in login/signup flows or contact forms where precision matters.
Adding a Multiline Bio Input
BioInput.tsx
import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export default function BioInput() {
const [bio, setBio] = useState('');
return (
<View style={styles.container}>
<Text style={styles.label}>Bio</Text>
<TextInput
style={styles.input}
value={bio}
onChangeText={setBio}
placeholder="Write something about yourself..."
multiline
numberOfLines={4}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
marginBottom: 16
},
label: {
fontWeight: 'bold',
fontSize: 16,
marginBottom: 8
},
input: {
padding: 10,
height: 100,
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 6,
textAlignVertical: 'top' // Ensures text starts at top-left inside multiline box
}
});
- Many social or user-focused apps include a Bio field. This is often a larger, multiline input where users can describe themselves or their services.
- We'll use the `multiline` and `numberOfLines` props to expand the input, and `textAlignVertical: 'top'` to ensure the text starts at the top of the box.
Reusable InputLabel Component
InputLabel.tsx
import React from 'react';
import { Text, StyleSheet } from 'react-native';
type InputLabelProps = {
text: string;
fontSize?: number;
fontColor?: string;
fontWeight?: 'normal' | 'bold';
};
export default function InputLabel(props: InputLabelProps) {
const { text, fontSize = 16, fontColor = '#000', fontWeight = 'bold' } = props;
return (
<Text style={[styles.label, { fontSize, color: fontColor, fontWeight }]}>
{text}
</Text>
);
}
const styles = StyleSheet.create({
label: {
marginBottom: 8
}
});
- Repetition leads to bugs. Let’s extract the label into a reusable component so every input field uses consistent spacing and font styles.
- This makes it easier to apply global changes and keeps the code DRY.
Key Takeaways
- Each input field should solve a specific UX need—name, email, and bio all have different expectations.
- Avoid hardcoded styles in JSX—use
StyleSheet.create()
to isolate and organize styles. - When function components accept props, deconstruct them right after the signature for clarity.
- Create reusable UI elements like
InputLabel
to eliminate duplication and speed up development. - When using
multiline
, be sure to addtextAlignVertical: 'top'
so the text appears at the correct position inside the input.