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, 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: