Back

Step by Step Guide to Building a Firestore API Integration in JS

Aug 9, 20248 minute read

Introduction

Hey there, fellow developer! Ready to supercharge your app with Firestore? You're in the right place. Firestore is Google's flexible, scalable NoSQL cloud database, and integrating it into your JS project can be a game-changer. Let's dive in and get your hands dirty with some code!

Prerequisites

Before we jump in, make sure you've got:

  • Node.js and npm installed (you're a pro, so I'm sure you do)
  • A Firebase project set up (if not, hop over to the Firebase console and create one)
  • A Firestore database ready to go

Got all that? Great! Let's build something awesome.

Setting up the project

First things first, let's get our project structure in place:

mkdir firestore-api-integration cd firestore-api-integration npm init -y npm install firebase

Easy peasy, right? Now we're ready to start coding!

Configuring Firebase

Let's get Firebase up and running in your project:

const { initializeApp } = require('firebase/app'); const { getFirestore } = require('firebase/firestore'); const firebaseConfig = { // Your config here }; const app = initializeApp(firebaseConfig); const db = getFirestore(app);

Just replace the firebaseConfig object with your own, and you're good to go!

Basic CRUD operations

Now for the fun part - let's interact with our database!

Create

Adding a document is a breeze:

const { collection, addDoc } = require('firebase/firestore'); async function addUser(name, age) { try { const docRef = await addDoc(collection(db, 'users'), { name: name, age: age }); console.log('Document written with ID: ', docRef.id); } catch (e) { console.error('Error adding document: ', e); } }

Read

Need to fetch some data? No problem:

const { collection, getDocs } = require('firebase/firestore'); async function getUsers() { const querySnapshot = await getDocs(collection(db, 'users')); querySnapshot.forEach((doc) => { console.log(`${doc.id} => ${JSON.stringify(doc.data())}`); }); }

Update

Updating is just as simple:

const { doc, updateDoc } = require('firebase/firestore'); async function updateUser(id, newAge) { const userRef = doc(db, 'users', id); await updateDoc(userRef, { age: newAge }); }

Delete

And when it's time to say goodbye:

const { doc, deleteDoc } = require('firebase/firestore'); async function deleteUser(id) { await deleteDoc(doc(db, 'users', id)); }

Advanced Firestore features

Ready to level up? Let's look at some cooler features.

Real-time listeners

Stay up-to-date with real-time data:

const { collection, onSnapshot } = require('firebase/firestore'); const unsubscribe = onSnapshot(collection(db, 'users'), (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === 'added') { console.log('New user: ', change.doc.data()); } if (change.type === 'modified') { console.log('Modified user: ', change.doc.data()); } if (change.type === 'removed') { console.log('Removed user: ', change.doc.data()); } }); }); // Call unsubscribe() when you're done listening

Batch writes

Need to update multiple documents? Batch it up:

const { writeBatch, doc } = require('firebase/firestore'); async function batchUpdate() { const batch = writeBatch(db); const user1Ref = doc(db, 'users', 'user1'); batch.update(user1Ref, {age: 30}); const user2Ref = doc(db, 'users', 'user2'); batch.update(user2Ref, {age: 35}); await batch.commit(); }

Error handling and security

Don't forget to handle those pesky errors and keep your data safe!

try { // Your Firestore operations here } catch (error) { console.error('Error:', error); // Handle the error appropriately }

And remember to set up your Firestore security rules in the Firebase console. Here's a simple example:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Optimizing performance

To keep your app speedy, remember to:

  1. Create indexes for your complex queries
  2. Use pagination for large data sets
const { collection, query, orderBy, limit, startAfter, getDocs } = require('firebase/firestore'); async function getPagedUsers(lastVisible, pageSize = 10) { const usersQuery = query(collection(db, 'users'), orderBy('name'), startAfter(lastVisible), limit(pageSize) ); const querySnapshot = await getDocs(usersQuery); // Process the results }

Testing the API

Last but not least, don't forget to test your API! Jest is a great choice for testing:

const { addUser, getUser } = require('./your-firestore-api'); test('adds a user and retrieves it', async () => { const userId = await addUser('John Doe', 30); const user = await getUser(userId); expect(user.name).toBe('John Doe'); expect(user.age).toBe(30); });

Conclusion

And there you have it! You've just built a robust Firestore API integration. Pretty cool, right? Remember, this is just the tip of the iceberg. Firestore has a ton of powerful features to explore, so keep experimenting and building awesome things!

Happy coding, and may your databases always be fast and your queries always return!