Paramclasses Academy - Blog

Tutorials Details

←
Post 30 of 39
→

What is Store and Retrieve App Data Using Cloud Firestore ?

What is Store and Retrieve App Data Using Cloud Firestore ?

November 5, 2026

1. Introduction

Modern mobile applications need a database to store information such as user profiles, student records, product details, messages, and other application data.

Cloud Firestore is a flexible, scalable NoSQL cloud database provided by Firebase. It allows React Native applications to store, retrieve, update, delete, and synchronize data across devices.

In this tutorial, we will learn how to integrate Cloud Firestore into a React Native application using the Firebase JavaScript SDK.

By the end of this tutorial, you will build a Student Data Management App that can save student information to Firebase and display stored records in real time.

2. What Is Cloud Firestore?

Cloud Firestore is a cloud-hosted NoSQL document database.

Unlike traditional relational databases that organize information into tables and rows, Firestore organizes data into collections and documents.

Firestore Structure

  • Database: The main storage system.

  • Collection: A group of related documents.

  • Document: A record containing fields and values.

  • Field: An individual piece of information.

Example:

students (Collection)
│
├── student001 (Document)
│   ├── name: "Rahul"
│   ├── course: "React Native"
│   └── status: "Active"
│
├── student002 (Document)
│   ├── name: "Amit"
│   ├── course: "Java"
│   └── status: "Active"
│
└── student003 (Document)
    ├── name: "Priya"
    ├── course: "Python"
    └── status: "Active"

3. Features of Cloud Firestore

  1. Cloud Database: Store application data online.

  2. Real-Time Synchronization: Automatically receive updates when database information changes.

  3. Offline Support: Supported client SDKs can work with cached data and synchronize changes when connectivity returns.

  4. Scalable Storage: Designed to support applications as their data grows.

  5. Security Rules: Control who can read and write database information.

  6. Flexible Data Structure: Store strings, numbers, booleans, arrays, maps, and timestamps.

  7. Query Support: Retrieve records using filters and sorting.

4. What We Will Build

Our project will be a Student Data Management App.

The application will provide these features:

  • Add a new student.

  • Store student details in Cloud Firestore.

  • Retrieve student records.

  • Display records in a mobile application.

  • Receive real-time database updates.

  • Change a student's status.

  • Delete student records.

5. Requirements

Before starting, make sure you have:

  • Node.js and npm installed.

  • Expo development environment configured.

  • Android Studio or Expo Go.

  • A Firebase account.

  • Basic knowledge of JavaScript and React Native.

6. Create a New React Native Project

Open your terminal and execute:

npx create-expo-app@latest FirestoreStudentApp --template blank

Navigate to the project directory:

cd FirestoreStudentApp

Start the development server:

npx expo start

Your React Native project is now ready.

7. Install Firebase

Install the Firebase JavaScript SDK using Expo:

npx expo install firebase

This SDK allows our React Native application to communicate with Firebase services, including Cloud Firestore.

For this tutorial, we will use the Firebase JavaScript SDK because it supports the Expo Go development workflow.

8. Create a Firebase Project

Follow these steps:

  1. Open the Firebase Console.

  2. Click Create a project.

  3. Enter the project name: FirestoreStudentApp.

  4. Complete the project creation process.

  5. Open your Firebase project.

  6. Select the Web App icon to register a web application.

  7. Enter an application nickname.

  8. Register the application.

  9. Copy the Firebase configuration object.

Firebase Console:

https://console.firebase.google.com/

Important: Registering a Web App here provides the configuration required by the Firebase JavaScript SDK. It does not mean your project is only a web application.

9. Enable Cloud Firestore

Now we need to create our Firestore database.

  1. Open your Firebase project.

  2. Navigate to Build → Firestore Database.

  3. Click Create database.

  4. Select a database location.

  5. Complete the setup process.

  6. Open the Data tab.

Your Cloud Firestore database is now ready.

10. Configure Firebase in React Native

Create a new file in the root directory:

FirestoreStudentApp/
│
├── App.js
├── firebaseConfig.js
├── package.json
└── node_modules/

Open firebaseConfig.js and add:

import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID",
};

const app = initializeApp(firebaseConfig);

const db = getFirestore(app);

export { db };

Replace the placeholder values with the configuration values from your Firebase project.

We have now initialized Firebase and connected Cloud Firestore to our React Native application.

11. Understand Important Firestore Functions

Before writing the main application, understand these functions:

Function Purpose
collection() References a collection
addDoc() Adds a document with an automatically generated ID
getDocs() Retrieves documents once
getDoc() Retrieves a single document
onSnapshot() Listens for real-time changes
updateDoc() Updates document fields
deleteDoc() Deletes a document
serverTimestamp() Stores a server-generated timestamp

These functions are part of Firebase's modular JavaScript SDK.

12. Create the Student Data Management App

Open App.js.

We will build an interface containing:

  • Student name input.

  • Course name input.

  • Add Student button.

  • Student records list.

  • Active/Inactive status button.

  • Delete button.

Complete App.js Code

import React, { useEffect, useState } from "react";

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

import {
  collection,
  addDoc,
  onSnapshot,
  updateDoc,
  deleteDoc,
  doc,
  serverTimestamp,
  query,
  orderBy,
} from "firebase/firestore";

import { db } from "./firebaseConfig";

export default function App() {
  const [name, setName] = useState("");
  const [course, setCourse] = useState("");
  const [students, setStudents] = useState([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);

  // Listen to Firestore records in real time
  useEffect(() => {
    const studentsRef = collection(db, "students");

    const studentsQuery = query(
      studentsRef,
      orderBy("createdAt", "desc")
    );

    const unsubscribe = onSnapshot(
      studentsQuery,
      (snapshot) => {
        const studentList = snapshot.docs.map((item) => ({
          id: item.id,
          ...item.data(),
        }));

        setStudents(studentList);
        setLoading(false);
      },
      (error) => {
        console.error("Firestore Error:", error);
        Alert.alert("Error", "Unable to retrieve student records.");
        setLoading(false);
      }
    );

    // Remove the listener when the component unmounts
    return unsubscribe;
  }, []);

  // Add a new student
  const addStudent = async () => {
    if (!name.trim() || !course.trim()) {
      Alert.alert("Validation", "Please enter all student details.");
      return;
    }

    try {
      setSaving(true);

      await addDoc(collection(db, "students"), {
        name: name.trim(),
        course: course.trim(),
        status: "Active",
        createdAt: serverTimestamp(),
      });

      setName("");
      setCourse("");

      Alert.alert("Success", "Student added successfully.");
    } catch (error) {
      console.error("Add Error:", error);
      Alert.alert("Error", "Unable to save student data.");
    } finally {
      setSaving(false);
    }
  };

  // Change student status
  const toggleStatus = async (student) => {
    try {
      const studentRef = doc(db, "students", student.id);

      await updateDoc(studentRef, {
        status: student.status === "Active" ? "Inactive" : "Active",
      });
    } catch (error) {
      console.error("Update Error:", error);
      Alert.alert("Error", "Unable to update student status.");
    }
  };

  // Delete student
  const removeStudent = (studentId) => {
    Alert.alert(
      "Delete Student",
      "Are you sure you want to delete this student?",
      [
        { text: "Cancel", style: "cancel" },
        {
          text: "Delete",
          style: "destructive",
          onPress: async () => {
            try {
              await deleteDoc(doc(db, "students", studentId));
            } catch (error) {
              console.error("Delete Error:", error);
              Alert.alert("Error", "Unable to delete student.");
            }
          },
        },
      ]
    );
  };

  // Render each student
  const renderStudent = ({ item }) => {
    return (
      <View style={styles.studentCard}>
        <Text style={styles.studentName}>
          {item.name}
        </Text>

        <Text style={styles.courseText}>
          Course: {item.course}
        </Text>

        <Text style={styles.statusText}>
          Status: {item.status}
        </Text>

        <View style={styles.buttonRow}>
          <Pressable
            style={styles.statusButton}
            onPress={() => toggleStatus(item)}
          >
            <Text style={styles.buttonText}>
              Change Status
            </Text>
          </Pressable>

          <Pressable
            style={styles.deleteButton}
            onPress={() => removeStudent(item.id)}
          >
            <Text style={styles.buttonText}>
              Delete
            </Text>
          </Pressable>
        </View>
      </View>
    );
  };

  return (
    <View style={styles.container}>
      <Text style={styles.heading}>
        Student Management
      </Text>

      <Text style={styles.subtitle}>
        Store and Retrieve Data Using Firestore
      </Text>

      <TextInput
        style={styles.input}
        placeholder="Enter student name"
        value={name}
        onChangeText={setName}
      />

      <TextInput
        style={styles.input}
        placeholder="Enter course name"
        value={course}
        onChangeText={setCourse}
      />

      <Pressable
        style={styles.addButton}
        onPress={addStudent}
        disabled={saving}
      >
        <Text style={styles.buttonText}>
          {saving ? "Saving..." : "Add Student"}
        </Text>
      </Pressable>

      <Text style={styles.listHeading}>
        Student Records ({students.length})
      </Text>

      {loading ? (
        <ActivityIndicator size="large" />
      ) : (
        <FlatList
          data={students}
          keyExtractor={(item) => item.id}
          renderItem={renderStudent}
          ListEmptyComponent={
            <Text style={styles.emptyText}>
              No student records found.
            </Text>
          }
        />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#F4F6FA",
    padding: 20,
    paddingTop: 60,
  },

  heading: {
    fontSize: 25,
    fontWeight: "bold",
    color: "#172554",
  },

  subtitle: {
    fontSize: 13,
    color: "#64748B",
    marginBottom: 20,
  },

  input: {
    backgroundColor: "#FFFFFF",
    padding: 14,
    borderRadius: 10,
    marginBottom: 12,
    borderWidth: 1,
    borderColor: "#CBD5E1",
  },

  addButton: {
    backgroundColor: "#2563EB",
    padding: 15,
    borderRadius: 10,
    alignItems: "center",
  },

  listHeading: {
    fontSize: 19,
    fontWeight: "bold",
    marginTop: 25,
    marginBottom: 12,
    color: "#172554",
  },

  studentCard: {
    backgroundColor: "#FFFFFF",
    padding: 15,
    borderRadius: 12,
    marginBottom: 12,
    elevation: 2,
  },

  studentName: {
    fontSize: 18,
    fontWeight: "bold",
    color: "#1E293B",
  },

  courseText: {
    marginTop: 6,
    color: "#475569",
  },

  statusText: {
    marginTop: 6,
    color: "#15803D",
  },

  buttonRow: {
    flexDirection: "row",
    marginTop: 12,
    gap: 10,
  },

  statusButton: {
    backgroundColor: "#0F766E",
    padding: 10,
    borderRadius: 7,
    flex: 1,
    alignItems: "center",
  },

  deleteButton: {
    backgroundColor: "#DC2626",
    padding: 10,
    borderRadius: 7,
    flex: 1,
    alignItems: "center",
  },

  buttonText: {
    color: "#FFFFFF",
    fontWeight: "bold",
  },

  emptyText: {
    textAlign: "center",
    color: "#64748B",
    marginTop: 25,
  },
});

13. Understand How Data Is Stored

When the user enters a student name and course, the addStudent() function executes.

The following code saves the information:

await addDoc(collection(db, "students"), {
  name: name.trim(),
  course: course.trim(),
  status: "Active",
  createdAt: serverTimestamp(),
});

Explanation:

  • collection(db, "students") selects the students collection.

  • addDoc() creates a new document.

  • name stores the student's name.

  • course stores the selected course.

  • status stores the student's current status.

  • serverTimestamp() stores the server-generated creation time.

Firestore automatically generates a unique document ID.

14. Retrieve Data from Cloud Firestore

The application uses the onSnapshot() function to listen for database changes.

const unsubscribe = onSnapshot(
  collection(db, "students"),
  (snapshot) => {
    const studentList = snapshot.docs.map((item) => ({
      id: item.id,
      ...item.data(),
    }));

    setStudents(studentList);
  }
);

Whenever a student record is added, updated, or deleted, the application receives the latest collection snapshot.

Retrieve Data Only Once

If you only want to fetch records once instead of continuously listening for changes, use getDocs():

import {
  collection,
  getDocs,
} from "firebase/firestore";

const fetchStudents = async () => {
  try {
    const snapshot = await getDocs(
      collection(db, "students")
    );

    const studentList = snapshot.docs.map((item) => ({
      id: item.id,
      ...item.data(),
    }));

    console.log(studentList);
  } catch (error) {
    console.log("Fetch Error:", error);
  }
};

Use getDocs() for one-time retrieval and onSnapshot() when the application needs live updates.

15. Update Student Data

The application changes a student's status using updateDoc().

await updateDoc(
  doc(db, "students", student.id),
  {
    status: "Inactive",
  }
);

This updates the specified document without replacing its other fields.

16. Delete Student Data

Use deleteDoc() to remove a student record.

await deleteDoc(
  doc(db, "students", studentId)
);

The real-time listener automatically receives the updated collection after deletion.

17. Test the Application

Follow these steps:

  1. Start your Expo project.

  2. Open the application using Expo Go or an appropriate development build.

  3. Enter a student name.

  4. Enter a course name.

  5. Press Add Student.

  6. Open Firebase Console.

  7. Navigate to Firestore Database.

  8. Open the students collection.

  9. Verify that the student record has been saved.

  10. Change the student's status in the application.

  11. Verify the updated value in Firebase.

  12. Delete the student and check that the document disappears.

Expected Result

Your application should display student records saved in Cloud Firestore. Changes made through the app should automatically appear in the database, and changes received through the real-time listener should update the mobile interface.

18. Firestore Security Rules

Database security is essential. Never use unrestricted database access in a production application.

For a real application, enable Firebase Authentication and use rules such as:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    match /students/{studentId} {
      allow read, write: if request.auth != null;
    }

  }
}

This example allows authenticated users to read and write student documents. A production student management application should also restrict users to the records they are authorized to access and validate permitted fields.

For a quick local demonstration, you may temporarily use the Firebase Console's test configuration, but do not publish an application with unrestricted rules.

19. Common Errors and Solutions

Error Possible Solution
Firebase configuration error Verify your Firebase configuration values
Permission denied Check Firestore Security Rules
Network request failed Check your internet connection
Collection not found Verify the collection name
Data not displaying Check your listener and console errors
Firebase module error Reinstall Firebase using Expo

 

 
   
   
   
   
   
   

20. Best Practices

  1. Use meaningful collection and document names.

  2. Validate user input before saving records.

  3. Use onSnapshot() only when real-time updates are required.

  4. Unsubscribe from listeners when they are no longer needed.

  5. Apply proper Firestore Security Rules.

  6. Avoid storing unnecessary information.

  7. Use pagination for large collections.

  8. Handle loading and error states.

  9. Use server timestamps for reliable creation times.

  10. Monitor Firestore reads, writes, storage, and billing.

21. Advantages of Cloud Firestore in React Native

  • No need to maintain your own database server for basic database operations.

  • Real-time data synchronization.

  • Flexible document-based storage.

  • Firebase Authentication integration.

  • Security Rules for access control.

  • Suitable for cross-platform applications.

  • Supports scalable application development.

22. Conclusion

In this tutorial, we learned how to connect a React Native application with Firebase Cloud Firestore.

We created a Student Data Management App and implemented the core database operations:

  • Create student records.

  • Retrieve student records.

  • Display real-time updates.

  • Update student status.

  • Delete student records.

Cloud Firestore is a useful database solution for applications that need cloud storage, real-time synchronization, and flexible data management.

By combining React Native with Firebase, developers can build modern mobile applications without having to create and maintain a custom database backend for every project.

23. Frequently Asked Questions

Q1. What is Cloud Firestore?

Cloud Firestore is a flexible, scalable NoSQL cloud database provided by Firebase.

Q2. Can React Native connect directly to Firestore?

Yes. React Native applications can use the Firebase JavaScript SDK to communicate with Cloud Firestore.

Q3. What is the difference between Firestore and Realtime Database?

Both are Firebase databases. Firestore uses collections and documents, while Realtime Database stores data as a large JSON tree.

Q4. What does addDoc() do?

It creates a new document with an automatically generated document ID.

Q5. What is the purpose of onSnapshot()?

It listens for database changes and provides updated snapshots.

Q6. Is Cloud Firestore free?

Firebase offers a free usage tier with limits. Charges may apply when usage exceeds the applicable free quotas.

Q7. Is Firestore secure?

Yes, when correctly configured with Firebase Security Rules and appropriate authentication and authorization.


Official Documentation:

←
Post 30 of 39
→