Lesson 80 of 60 – React Native TypeScript Mini Project
100%

React Native TypeScript Mini Project

In this lesson, we will build a small React Native application using TypeScript. The project will combine the concepts learned in the previous lessons, including components, interfaces, useState, forms, API-style data, navigation concepts, reusable components, and typed functions.

The goal of this project is to understand how different TypeScript concepts work together inside a real React Native application.

Project: We will create a simple Student Management application that displays students, allows adding a student, searches students, and uses reusable typed components.

1. Project Overview

Our mini project will contain a student management screen.

  • Display student records.
  • Add a new student.
  • Search students.
  • Use TypeScript interfaces.
  • Use typed React Native state.
  • Use reusable components.

2. Technologies Used

  • React Native
  • TypeScript
  • React Hooks
  • React Native components
  • TypeScript interfaces
  • Typed functions

3. Basic Project Structure

StudentApp/
    src/
        components/
            StudentCard.tsx
            StudentForm.tsx

        screens/
            StudentScreen.tsx

        types/
            student.ts

    App.tsx

4. Creating the Student Interface

export interface Student {
    id: number;
    name: string;
    age: number;
    course: string;
}

This interface describes the structure of a student object.

5. Creating Initial Student Data

const initialStudents: Student[] = [

    {
        id: 1,
        name: "Rahul",
        age: 20,
        course: "React Native"
    },

    {
        id: 2,
        name: "Priya",
        age: 21,
        course: "TypeScript"
    },

    {
        id: 3,
        name: "Amit",
        age: 19,
        course: "JavaScript"
    }

];

6. Creating Typed State

const [students, setStudents] =
    useState<Student[]>(
        initialStudents
    );

TypeScript knows that the state contains an array of Student objects.

7. Creating Search State

const [search, setSearch] =
    useState<string>("");

The search state stores the text entered by the user.

8. Creating a Typed Student Card

interface StudentCardProps {
    student: Student;
}

function StudentCard(
    { student }: StudentCardProps
): React.JSX.Element {

    return (
        <View>

            <Text>
                {student.name}
            </Text>

            <Text>
                {student.course}
            </Text>

        </View>
    );
}

9. Styling the Student Card

const styles = StyleSheet.create({

    card: {
        padding: 15,
        marginBottom: 10,
        borderWidth: 1,
        borderRadius: 8
    },

    name: {
        fontSize: 18,
        fontWeight: "bold"
    }

});

10. Displaying Student Data

<FlatList<Student>

    data={students}

    keyExtractor={(item) =>
        item.id.toString()
    }

    renderItem={({ item }) => (

        <StudentCard
            student={item}
        />

    )}

 />

11. Creating a Search Function

const filteredStudents =
    students.filter(
        (student: Student) =>

            student.name
                .toLowerCase()
                .includes(
                    search.toLowerCase()
                )
    );

12. Creating a Search Input

<TextInput

    placeholder="Search student"

    value={search}

    onChangeText={(
        text: string
    ) => setSearch(text)}

    style={styles.input}

/>

13. Creating Form State

interface StudentForm {
    name: string;
    age: string;
    course: string;
}

const [form, setForm] =
    useState<StudentForm>({

        name: "",
        age: "",
        course: ""

    });

14. Updating Form Fields

const updateField = (
    field: keyof StudentForm,
    value: string
): void => {

    setForm(
        previous => ({

            ...previous,

            [field]: value

        })
    );
};

The keyof operator ensures that only valid form field names can be passed to the function.

15. Creating a Reusable Input Component

interface InputProps {
    placeholder: string;
    value: string;
    onChangeText:
        (text: string) => void;
}

function AppInput(
    {
        placeholder,
        value,
        onChangeText
    }: InputProps
): React.JSX.Element {

    return (
        <TextInput

            placeholder={placeholder}

            value={value}

            onChangeText={onChangeText}

            style={styles.input}

        />
    );
}

16. Creating the Add Student Function

const addStudent = (): void => {

    const newStudent: Student = {

        id: Date.now(),

        name: form.name,

        age: Number(form.age),

        course: form.course

    };

    setStudents(
        previous => [
            ...previous,
            newStudent
        ]
    );

};

17. Form Validation

const validateForm = (): boolean => {

    if (
        !form.name ||
        !form.age ||
        !form.course
    ) {

        return false;

    }

    return true;
};

Validation can prevent incomplete student records from being added.

18. Adding Validation to addStudent

const addStudent = (): void => {

    if (!validateForm()) {

        Alert.alert(
            "Error",
            "Please fill all fields"
        );

        return;
    }

    const newStudent: Student = {

        id: Date.now(),

        name: form.name,

        age: Number(form.age),

        course: form.course

    };

    setStudents(
        previous => [
            ...previous,
            newStudent
        ]
    );

};

19. Clearing the Form

const clearForm = (): void => {

    setForm({

        name: "",
        age: "",
        course: ""

    });
};

20. Student Delete Function

const deleteStudent = (
    id: number
): void => {

    setStudents(
        previous =>

            previous.filter(
                student =>
                    student.id !== id
            )
    );
};

The function accepts only a number because student IDs are numbers.

21. Passing a Function to a Component

interface StudentCardProps {

    student: Student;

    onDelete:
        (id: number) => void;
}

Function props should be typed so that the child component knows how the function should be called.

22. Student Card with Delete Button

function StudentCard(
    {
        student,
        onDelete
    }: StudentCardProps
): React.JSX.Element {

    return (

        <View style={styles.card}>

            <Text style={styles.name}>
                {student.name}
            </Text>

            <Text>
                Age: {student.age}
            </Text>

            <Text>
                Course: {student.course}
            </Text>

            <Button
                title="Delete"
                onPress={() =>
                    onDelete(student.id)
                }
            />

        </View>
    );
}

23. Connecting the Student List

<FlatList<Student>

    data={filteredStudents}

    keyExtractor={(item) =>
        item.id.toString()
    }

    renderItem={({ item }) => (

        <StudentCard

            student={item}

            onDelete={
                deleteStudent
            }

        />

    )}

 />

24. Complete Mini Project Screen

import React, {
    useState
} from "react";

import {
    View,
    Text,
    TextInput,
    Button,
    FlatList,
    Alert,
    StyleSheet
} from "react-native";

interface Student {
    id: number;
    name: string;
    age: number;
    course: string;
}

interface StudentForm {
    name: string;
    age: string;
    course: string;
}

const initialStudents: Student[] = [

    {
        id: 1,
        name: "Rahul",
        age: 20,
        course: "React Native"
    },

    {
        id: 2,
        name: "Priya",
        age: 21,
        course: "TypeScript"
    }

];

export default function StudentScreen():
    React.JSX.Element {

    const [students, setStudents] =
        useState<Student[]>(
            initialStudents
        );

    const [search, setSearch] =
        useState<string>("");

    const [form, setForm] =
        useState<StudentForm>({

            name: "",
            age: "",
            course: ""

        });

    const updateField = (
        field: keyof StudentForm,
        value: string
    ): void => {

        setForm(
            previous => ({

                ...previous,

                [field]: value

            })
        );
    };

    const addStudent = (): void => {

        if (
            !form.name ||
            !form.age ||
            !form.course
        ) {

            Alert.alert(
                "Error",
                "Please fill all fields"
            );

            return;
        }

        const newStudent: Student = {

            id: Date.now(),

            name: form.name,

            age: Number(form.age),

            course: form.course

        };

        setStudents(
            previous => [
                ...previous,
                newStudent
            ]
        );

        setForm({

            name: "",
            age: "",
            course: ""

        });
    };

    const deleteStudent = (
        id: number
    ): void => {

        setStudents(
            previous =>

                previous.filter(
                    student =>
                        student.id !== id
                )
        );
    };

    const filteredStudents =
        students.filter(
            student =>

                student.name
                    .toLowerCase()
                    .includes(
                        search.toLowerCase()
                    )
        );

    return (

        <View style={styles.container}>

            <Text style={styles.title}>
                Student Management
            </Text>

            <TextInput
                placeholder="Search student"
                value={search}
                onChangeText={(
                    text: string
                ) => setSearch(text)}
                style={styles.input}
            />

            <TextInput
                placeholder="Student Name"
                value={form.name}
                onChangeText={(
                    text: string
                ) =>
                    updateField(
                        "name",
                        text
                    )
                }
                style={styles.input}
            />

            <TextInput
                placeholder="Age"
                value={form.age}
                keyboardType="numeric"
                onChangeText={(
                    text: string
                ) =>
                    updateField(
                        "age",
                        text
                    )
                }
                style={styles.input}
            />

            <TextInput
                placeholder="Course"
                value={form.course}
                onChangeText={(
                    text: string
                ) =>
                    updateField(
                        "course",
                        text
                    )
                }
                style={styles.input}
            />

            <Button
                title="Add Student"
                onPress={addStudent}
            />

            <FlatList<Student>

                data={filteredStudents}

                keyExtractor={(item) =>
                    item.id.toString()
                }

                renderItem={({
                    item
                }) => (

                    <View
                        style={styles.card}
                    >

                        <Text
                            style={styles.name}
                        >
                            {item.name}
                        </Text>

                        <Text>
                            Age: {item.age}
                        </Text>

                        <Text>
                            Course:
                            {item.course}
                        </Text>

                        <Button
                            title="Delete"
                            onPress={() =>
                                deleteStudent(
                                    item.id
                                )
                            }
                        />

                    </View>

                )}

            />

        </View>
    );
}

const styles = StyleSheet.create({

    container: {
        flex: 1,
        padding: 20
    },

    title: {
        fontSize: 24,
        fontWeight: "bold",
        marginBottom: 15
    },

    input: {
        borderWidth: 1,
        borderRadius: 8,
        padding: 10,
        marginBottom: 10
    },

    card: {
        padding: 15,
        marginTop: 10,
        borderWidth: 1,
        borderRadius: 8
    },

    name: {
        fontSize: 18,
        fontWeight: "bold"
    }

});

25. Connecting the Screen to App.tsx

import React from "react";

import StudentScreen
    from "./src/screens/StudentScreen";

export default function App():
    React.JSX.Element {

    return (
        <StudentScreen />
    );
}

The StudentScreen becomes the main screen of the application.

26. Concepts Used in This Project

  • TypeScript interfaces
  • Type aliases and typed objects
  • useState
  • Typed arrays
  • Function parameter types
  • Function return types
  • keyof
  • React Native TextInput
  • React Native Button
  • FlatList
  • Reusable components
  • Form validation

27. Improvements You Can Add

This mini project can be expanded into a complete student management application.

  • Student details screen
  • Edit student
  • Student profile
  • API integration using Axios
  • AsyncStorage
  • Authentication
  • React Navigation
  • Context API
  • Redux Toolkit
  • Backend database

28. Common Project Mistakes

  • Using any everywhere.
  • Not defining interfaces for data.
  • Using incorrect state types.
  • Not typing function parameters.
  • Passing incorrect props to components.
  • Forgetting to convert text input values to numbers.
  • Keeping all application logic inside one huge component.

29. Project Best Practices

  • Use interfaces for important data structures.
  • Use reusable components.
  • Separate screens from components.
  • Keep API code inside service files.
  • Keep shared types in a types folder.
  • Use typed functions.
  • Validate user input.
  • Use feature-based structure as the project grows.

30. Final Project Summary

In this mini project, we combined many TypeScript and React Native concepts to create a small Student Management application.

We created interfaces for students and forms, typed state, reusable components, search functionality, form validation, add and delete operations, and a FlatList for displaying student records.

This project provides a foundation for larger React Native applications where APIs, navigation, authentication, Context API, Redux Toolkit, and persistent storage can be added.

📌 Key Points

  • Use interfaces to describe application data.
  • Use typed state with useState.
  • Use reusable components for repeated UI.
  • Use FlatList<Student> for typed student data.
  • Use keyof for safe form field updates.
  • Type function parameters and return values.
  • Validate form data before creating records.
  • Separate screens, components, services, and types as projects grow.
  • This project can be extended with API, navigation, Context, Redux, and storage.

🧠 Quick Quiz

Question: Which TypeScript interface is used to describe the structure of a student object in this project?