React Native provides components such as
View, Text,
TextInput, Button,
Pressable, ScrollView, and
FlatList. TypeScript helps us use these components
correctly by checking their props, values, and event handlers.
Typing components means using TypeScript to describe the data and behavior used by a React Native component.
interface UserProps {
name: string;
age: number;
}
function User({
name,
age
}: UserProps): React.JSX.Element {
return (
<View>
<Text>{name}</Text>
<Text>{age}</Text>
</View>
);
}
Some commonly used React Native components are:
ViewTextTextInputButtonPressableScrollViewFlatListImageActivityIndicatorimport {
View,
Text
} from "react-native";
function Home(): React.JSX.Element {
return (
<View>
<Text>
Home Screen
</Text>
</View>
);
}
View is commonly used as a container for
other React Native components.
function Welcome(): React.JSX.Element {
const name: string = "Rahul";
return (
<Text>
Hello {name}
</Text>
);
}
The value displayed inside Text can come from
a typed variable.
import {
TextInput
} from "react-native";
const [name, setName] =
useState<string>("");
return (
<TextInput
value={name}
onChangeText={setName}
placeholder="Enter name"
/>
);
The name state is explicitly typed as a
string.
import {
Button
} from "react-native";
const handlePress = (): void => {
console.log("Pressed");
};
return (
<Button
title="Save"
onPress={handlePress}
/>
);
import {
Pressable,
Text
} from "react-native";
const handlePress = (): void => {
console.log("Pressed");
};
return (
<Pressable
onPress={handlePress}
>
<Text>
Press Me
</Text>
</Pressable>
);
TypeScript becomes especially useful when creating your own reusable React Native components.
interface WelcomeProps {
name: string;
}
function Welcome({
name
}: WelcomeProps): React.JSX.Element {
return (
<Text>
Welcome {name}
</Text>
);
}
<Welcome
name="Rahul"
/>
TypeScript checks that the required
name prop is provided.
interface StudentCardProps {
name: string;
age: number;
course: string;
}
function StudentCard({
name,
age,
course
}: StudentCardProps): React.JSX.Element {
return (
<View>
<Text>
Name: {name}
</Text>
<Text>
Age: {age}
</Text>
<Text>
Course: {course}
</Text>
</View>
);
}
interface UserProps {
name: string;
email?: string;
}
function User({
name,
email
}: UserProps): React.JSX.Element {
return (
<View>
<Text>
{name}
</Text>
{email && (
<Text>
{email}
</Text>
)}
</View>
);
}
interface ButtonProps {
disabled: boolean;
}
function SaveButton({
disabled
}: ButtonProps): React.JSX.Element {
return (
<Button
title="Save"
disabled={disabled}
onPress={() => {}}
/>
);
}
interface ButtonProps {
onPress: () => void;
}
function CustomButton({
onPress
}: ButtonProps): React.JSX.Element {
return (
<Button
title="Click"
onPress={onPress}
/>
);
}
A function prop allows a parent component to control an action performed by the child.
interface StudentProps {
id: number;
onSelect: (id: number) => void;
}
function StudentButton({
id,
onSelect
}: StudentProps): React.JSX.Element {
return (
<Button
title="Select"
onPress={() =>
onSelect(id)
}
/>
);
}
import {
ReactNode
} from "react";
interface CardProps {
children: ReactNode;
}
function Card({
children
}: CardProps): React.JSX.Element {
return (
<View>
{children}
</View>
);
}
ReactNode can be used when a component accepts
React content through children.
import {
Image
} from "react-native";
function ProfileImage(): React.JSX.Element {
return (
<Image
source={{
uri: "https://example.com/user.jpg"
}}
style={{
width: 100,
height: 100
}}
/>
);
}
The Image component is used to display images
in React Native applications.
import {
ScrollView,
Text
} from "react-native";
function About(): React.JSX.Element {
return (
<ScrollView>
<Text>
React Native content
</Text>
<Text>
More content
</Text>
</ScrollView>
);
}
interface Student {
id: number;
name: string;
}
interface Props {
students: Student[];
}
function StudentList({
students
}: Props): React.JSX.Element {
return (
<FlatList
data={students}
keyExtractor={(item) =>
item.id.toString()
}
renderItem={({ item }) => (
<Text>
{item.name}
</Text>
)}
/>
);
}
interface Student {
id: string;
name: string;
}
interface StudentSection {
title: string;
data: Student[];
}
TypeScript can describe the structure of section data
before passing it to a SectionList.
import {
ActivityIndicator
} from "react-native";
const [loading, setLoading] =
useState<boolean>(true);
return (
<View>
{loading && (
<ActivityIndicator
size="large"
/>
)}
</View>
);
interface User {
id: number;
name: string;
}
const [user, setUser] =
useState<User | null>(null);
The state can contain either a User object or
null.
interface Product {
id: number;
name: string;
price: number;
}
function ProductCard({
product
}: {
product: Product;
}): React.JSX.Element {
return (
<View>
<Text>
{product.name}
</Text>
<Text>
₹{product.price}
</Text>
</View>
);
}
const handleNameChange = (
text: string
): void => {
setName(text);
};
return (
<TextInput
value={name}
onChangeText={handleNameChange}
/>
);
React Native's onChangeText callback provides
the new text directly as a string.
const handlePress = (): void => {
console.log(
"Pressable clicked"
);
};
return (
<Pressable
onPress={handlePress}
>
<Text>
Open
</Text>
</Pressable>
);
import {
StyleSheet,
View
} from "react-native";
function Screen(): React.JSX.Element {
return (
<View
style={styles.container}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20
}
});
StyleSheet.create() provides type checking for
React Native style properties.
interface AppButtonProps {
title: string;
onPress: () => void;
disabled?: boolean;
}
function AppButton({
title,
onPress,
disabled = false
}: AppButtonProps): React.JSX.Element {
return (
<Button
title={title}
onPress={onPress}
disabled={disabled}
/>
);
}
interface AppInputProps {
value: string;
placeholder?: string;
onChangeText: (
text: string
) => void;
}
function AppInput({
value,
placeholder,
onChangeText
}: AppInputProps): React.JSX.Element {
return (
<TextInput
value={value}
placeholder={placeholder}
onChangeText={onChangeText}
/>
);
}
import {
useState
} from "react";
import {
View,
Text,
TextInput,
Button,
StyleSheet
} from "react-native";
interface Student {
id: number;
name: string;
course: string;
}
interface StudentCardProps {
student: Student;
onDelete: (
id: number
) => void;
}
function StudentCard({
student,
onDelete
}: StudentCardProps): React.JSX.Element {
return (
<View style={styles.card}>
<Text style={styles.name}>
{student.name}
</Text>
<Text>
ID: {student.id}
</Text>
<Text>
Course: {student.course}
</Text>
<Button
title="Delete"
onPress={() =>
onDelete(student.id)
}
/>
</View>
);
}
function App(): React.JSX.Element {
const [name, setName] =
useState<string>("");
const [students, setStudents] =
useState<Student[]>([]);
const addStudent = (): void => {
if (!name.trim()) {
return;
}
const student: Student = {
id: Date.now(),
name: name,
course: "React Native"
};
setStudents(
previousStudents => [
...previousStudents,
student
]
);
setName("");
};
const deleteStudent = (
id: number
): void => {
setStudents(
previousStudents =>
previousStudents.filter(
student =>
student.id !== id
)
);
};
return (
<View style={styles.container}>
<Text style={styles.title}>
Student Management
</Text>
<TextInput
style={styles.input}
value={name}
onChangeText={setName}
placeholder="Enter student name"
/>
<Button
title="Add Student"
onPress={addStudent}
/>
{students.map(student => (
<StudentCard
key={student.id}
student={student}
onDelete={deleteStudent}
/>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
paddingTop: 60
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 20
},
input: {
borderWidth: 1,
padding: 10,
marginBottom: 15
},
card: {
borderWidth: 1,
padding: 15,
marginTop: 10
},
name: {
fontSize: 18,
fontWeight: "bold"
}
});
export default App;
This example combines interfaces, typed props, typed
state, TextInput, Button,
callback functions, arrays, reusable components, and
React Native styles.
onPress and onChangeText.ReactNode when a custom component accepts children.null.Question: Which TypeScript feature is commonly used to define the props of a custom React Native component?