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
- Introduction to React Native
- React Native Components
- React Hooks
- Node.js and Npm
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, developed using React Native, offers a seamless experience for users to input their course information including course name, credit hours, and grade. With its user-friendly interface featuring text input fields, a grade picker, and interactive buttons for adding and deleting courses, the app dynamically calculates the user’s GPA based on the entered data. Powered by React Native’s state management capabilities, it efficiently captures user input, performs calculations, and showcases the comprehensive course list alongside the calculated GPA.
Example: The given code provides an illustration of a mobile app called GPA Calculator, developed using React Native. This app comprises three main components: CourseForm, CourseList, and GPACalculator. The CourseForm component is responsible for managing the input of course data and ensures validation before adding new courses. On the other hand, the CourseList component displays the list of courses with options to delete entries. Lastly, the GPACalculator component orchestrates the entire application by calculating the GPA based on entered 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: