Wednesday, August 27, 2025
HomeLanguagesCreate a GPA Calculator using React Native

Create a GPA Calculator using React Native

A GPA calculator proves to be a useful tool for students who want to monitor their academic progress. In this article, we will build a GPA calculator using React Native, a popular framework for building mobile applications.

Preview Image

Prerequisites

Steps to Create React Native Application

Step 1: Create a React Native Application

Create a new React Native project for gpaCalculatorApp

npx create-expo-app gpaCalculatorApp

Step 2: ​Change the directory to the project folder:

cd gpaCalculatorApp

Project Structure

Package.json

{
  "dependencies": {
    "react-native-paper": "4.9.2",
    "@expo/vector-icons": "^13.0.0"
  }
}

Approach

The GPA Calculator app, de­veloped using React Native­, offers a seamless e­xperience for use­rs to input their course information including course name­, credit hours, and grade. With its user-frie­ndly interface featuring te­xt input fields, a grade picker, and inte­ractive buttons for adding and deleting course­s, the app dynamically calculates the use­r’s GPA based on the ente­red data. Powered by Re­act Native’s state manageme­nt capabilities, it efficiently capture­s user input, performs calculations, and showcases the­ comprehensive course­ list alongside the calculated GPA.

Example: The give­n code provides an illustration of a mobile app calle­d GPA Calculator, developed using Re­act Native. This app comprises three­ main components: CourseForm, CourseList, and GPACalculator. The­ CourseForm component is responsible­ for managing the input of course data and ensure­s validation before adding new course­s. On the other hand, the Course­List component displays the list of courses with options to de­lete entrie­s. Lastly, the GPACalculator component orchestrate­s the entire application by calculating the­ GPA based on entere­d courses and presenting it alongside­ the course list.

Javascript




import React, { useState } from "react";
import {
    View,
    Text,
    TextInput,
    TouchableOpacity,
    ScrollView,
    StyleSheet,
} from "react-native";
import RNPickerSelect from "react-native-picker-select";
import { styles } from "./styles";
  
const gradePoints = {
    "A+": 4.0,
    A: 4.0,
    "A-": 3.7,
    "B+": 3.3,
    B: 3.0,
    "B-": 2.7,
    "C+": 2.3,
    C: 2.0,
    "C-": 1.7,
    "D+": 1.3,
    D: 1.0,
    "D-": 0.7,
};
  
const CustomButton = ({ title, onPress, style }) => {
    return (
        <TouchableOpacity onPress={onPress}>
            <View style={[styles.customButton, style]}>
                <Text style={styles.customButtonText}>
                    {title}
                </Text>
            </View>
        </TouchableOpacity>
    );
};
  
const CourseForm = ({ onAddCourse }) => {
    const [courseInfo, setCourseInfo] = useState({
        courseName: "",
        creditHours: "0",
        grade: "A+",
    });
  
    const handleInputChange = (name, value) => {
        setCourseInfo({
            ...courseInfo,
            [name]: value,
        });
    };
  
    const handleAddCourse = () => {
        const { courseName, creditHours, grade } =
            courseInfo;
        if (
            courseName &&
            parseFloat(creditHours) > 0 &&
            grade
        ) {
            const newCourse = {
                courseName,
                creditHours: parseFloat(creditHours),
                grade,
            };
  
            onAddCourse(newCourse);
            setCourseInfo({
                courseName: "",
                creditHours: "0",
                grade: "A+",
            });
        } else {
            alert("Please enter valid course details.");
        }
    };
  
    return (
        <View style={styles.section}>
            <Text style={styles.label}>Course</Text>
            <TextInput
                value={courseInfo.courseName}
                onChangeText={(text) =>
                    handleInputChange("courseName", text)
                }
                style={styles.input}
            />
  
            <Text style={styles.label}>Credits</Text>
            <TextInput
                value={courseInfo.creditHours}
                onChangeText={(text) =>
                    handleInputChange("creditHours", text)
                }
                keyboardType="numeric"
                style={styles.input}
            />
  
            <Text style={styles.label}>Grade</Text>
            <RNPickerSelect
                value={courseInfo.grade}
                onValueChange={(value) =>
                    handleInputChange("grade", value)
                }
                style={styles.picker}
                items={Object.keys(gradePoints).map(
                    (key) => ({
                        label: key,
                        value: key,
                    })
                )}
            />
  
            <CustomButton
                title="Add"
                onPress={handleAddCourse}
                style={[
                    styles.addButton,
                    courseInfo.courseName &&
                    parseFloat(courseInfo.creditHours) >
                        0 &&
                    courseInfo.grade
                        ? styles.addButtonHover
                        : null,
                ]}
            />
        </View>
    );
};
  
const CourseList = ({
    courses,
    onDeleteCourse,
    calculateGPA,
}) => {
    return (
        <View style={styles.section}>
            <Text style={styles.header}>Course List</Text>
            <ScrollView style={styles.list}>
                <View style={styles.listHeader}>
                    <Text>Course</Text>
                    <Text>Credits</Text>
                    <Text>Grade</Text>
                    <Text>Action</Text>
                </View>
                {courses.map((course, index) => (
                    <View
                        style={styles.listItem}
                        key={index}
                    >
                        <Text>{course.courseName}</Text>
                        <Text>{course.creditHours}</Text>
                        <Text>{course.grade}</Text>
                        <TouchableOpacity
                            style={styles.deletebtn}
                            onPress={() =>
                                onDeleteCourse(index)
                            }
                        >
                            <Text
                                style={styles.deletebtntext}
                            >
                                Delete
                            </Text>
                        </TouchableOpacity>
                    </View>
                ))}
            </ScrollView>
  
            <Text style={styles.gpa}>
                GPA: {calculateGPA().toFixed(2)}
            </Text>
        </View>
    );
};
  
const App = () => {
    const [courses, setCourses] = useState([]);
  
    const addCourse = (newCourse) => {
        setCourses([...courses, newCourse]);
    };
  
    const deleteCourse = (index) => {
        const updatedCourses = courses.filter(
            (course, i) => i !== index
        );
        setCourses(updatedCourses);
    };
  
    const calculateGPA = () => {
        let totalGradePoints = 0;
        let totalCreditHours = 0;
  
        courses.forEach((course) => {
            totalGradePoints +=
                gradePoints[course.grade] *
                course.creditHours;
            totalCreditHours += course.creditHours;
        });
  
        return totalCreditHours === 0
            ? 0
            : totalGradePoints / totalCreditHours;
    };
  
    return (
        <View style={styles.container}>
            <Text style={styles.title}>GPA Calculator</Text>
            <CourseForm onAddCourse={addCourse} />
            <CourseList
                courses={courses}
                onDeleteCourse={deleteCourse}
                calculateGPA={calculateGPA}
            />
        </View>
    );
};
  
export default App;


Javascript




//styles.js
  
import { StyleSheet } from "react-native";
  
const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 16,
        backgroundColor: "#f0f0f0",
    },
    title: {
        fontSize: 25,
        fontWeight: "bold",
        marginBottom: 10,
        textAlign: "center",
        color: "#333",
        margin: 10,
    },
    section: {
        marginBottom: 16,
        backgroundColor: "#fff",
        padding: 20,
        borderRadius: 5,
        borderWidth: 1,
        borderColor: "#ced4da",
        shadowColor: "grey",
        shadowOffset: {
            width: 0,
            height: 6,
        },
        shadowOpacity: 1,
        shadowRadius: 15,
        elevation: 5,
    },
    label: {
        fontSize: 16,
        marginBottom: 8,
        color: "#333",
    },
    input: {
        borderColor: "#ced4da",
        borderWidth: 1,
        borderRadius: 4,
        padding: 8,
        marginBottom: 8,
        fontSize: 16,
        color: "#333",
    },
    header: {
        fontSize: 18,
        fontWeight: "bold",
        marginBottom: 10,
        textAlign: "center",
        color: "#333",
    },
    list: {
        maxHeight: 200,
    },
    listHeader: {
        flexDirection: "row",
        justifyContent: "space-between",
        borderBottomWidth: 1,
        borderColor: "#ccc",
        marginBottom: 10,
        paddingBottom: 10,
    },
    listItem: {
        flexDirection: "row",
        justifyContent: "space-between",
        borderBottomWidth: 1,
        borderColor: "#ccc",
        marginBottom: 8,
        paddingBottom: 8,
    },
    gpa: {
        fontSize: 20,
        fontWeight: "bold",
        marginTop: 10,
        textAlign: "center",
        color: "#333",
    },
    addButton: {
        padding: 9.5,
        backgroundColor: "#fff",
        color: "#1d9bf0",
        borderWidth: 1,
        borderColor: "#1d9bf0",
        borderRadius: 4,
        fontWeight: "bold",
        transition: "0.5s all",
        textAlign: "center",
    },
    addButtonHover: {
        color: "white",
        backgroundColor: "#1d9bf0",
        borderColor: "#1d9bf0",
        borderWidth: 1,
    },
    deletebtn: {
        padding: 9.5,
        color: "#1d9bf0",
        fontWeight: "bold",
        textAlign: "center",
        backgroundColor: "red",
        borderRadius: 15,
    },
    deletebtntext: {
        color: "white",
    },
    picker: {
        fontSize: 16,
        paddingVertical: 12,
        paddingHorizontal: 10,
        borderWidth: 1,
        borderColor: "gray",
        borderRadius: 4,
        color: "black",
        paddingRight: 30,
    },
});
  
export { styles };


Steps to Run:

To run react native application use the following command:

npx expo start
  • To run on Android:
npx react-native run-android
  • To run on iOS:
npx react-native run-ios

Output:

Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, neveropen Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!
Dominic
Dominichttp://wardslaus.com
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

Most Popular

Dominic
32236 POSTS0 COMMENTS
Milvus
80 POSTS0 COMMENTS
Nango Kala
6609 POSTS0 COMMENTS
Nicole Veronica
11779 POSTS0 COMMENTS
Nokonwaba Nkukhwana
11828 POSTS0 COMMENTS
Shaida Kate Naidoo
6719 POSTS0 COMMENTS
Ted Musemwa
7002 POSTS0 COMMENTS
Thapelo Manthata
6678 POSTS0 COMMENTS
Umr Jansen
6690 POSTS0 COMMENTS