what is a serverless web application?
A serverless web application is a web application built using a serverless architecture. The server-side logic is handled by a cloud provider, such as AWS, Google Cloud, or Microsoft Azure, rather than needing to set up and maintain one or more servers. In a serverless web application developers write code as functions that are triggered by events such as HTTP requests or changes to a database.
Prerequisites
Before you get started, make sure you have the following installed:
Node.js (version 10 or higher)
npm or yarn
Firebase SDK (you can install it by running "npm install firebase" or "yarn add firebase" in your terminal)
Set up a Firebase project
The first step is to create a Firebase project and enable the services you need. follow these steps:
Go to Firebase and click on "Go to console"
Click "Add project" to create a project
Once the project is created, click on "add Firebase to your web app" and follow the prompts to set up Firebase Hosting, Authentication, and Cloud Firestore.
copy the configuration code that appears because you will need it in your React application
Create a React project
Now that you have a Firebase project setup it's time to create a React application using Vite, follow these steps:
if you are using npm, open your terminal and run "npm create vite@latest react-firebase-app" to create a new React app. If you are using yarn run "yarn create Vite react-firebase-app" instead.
Once the app is created, navigate to its directory by running "cd react-firebase-app".
Run "npm run dev" if you are using npm or "yarn run dev" if you are using yarn to start the development server.
open your localhost in your browser to see the app running.
Connect your react app to Firebase
To connect your React app to Firebase, follow these steps:
In your React app directory run "npm install firebase" if you are using npm or run "yarn add firebase" if you are using yarn to install the firebase sdk
Create a new file called "firebase.jsx" in your src directory. note that if you used Vite to create your application you would be using ".jsx" instead of ".js"
To configure Firebase, you need to add the Firebase configuration code you copied earlier to the "firebase.jsx" file you just created. It would look like the code below.
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyBgFxosqoGF8b9RX1ZIk_zwKI7oLFkDZok",
authDomain: "mrdareauth.firebaseapp.com",
projectId: "mrdareauth",
storageBucket: "mrdareauth.appspot.com",
messagingSenderId: "867798194052",
appId: "1:867798194052:web:d1981f8766c25509196fd1",
measurementId: "G-55PP94TD82"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
Importing Firebase Functions for App Features
Now that your app is connected to Firebase, you can start implementing features like user authentication, storage etc. To implement features, you would need to import some functions from Firebase. The code below shows how you can import the authentication and storage feature functions. (Note that you would import them in your 'firebase.jsx' file)
import {getAuth} from "firebase/auth"
import {getFirestore} from "firebase/firestore"
After importing the functions you can then wrap the app variable in them and assign them to a variable so that they can be exported and used in other components. the code below shows how it would look like
const auth = getAuth(app) //initializes the Firebase Authentication service for your app
const db = getFirestore(app) //initializes the Firebase firestore service for your app
export {auth, db} //export auth and db so that it can be used in other components
After doing all of that, your code should look like the code below
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import {getAuth} from "firebase/auth"
import {getFirestore} from "firebase/firestore"
const firebaseConfig = {
apiKey: "AIzaSyBgFxosqoGF8b9RX1ZIk_zwKI7oLFkDZok",
authDomain: "mrdareauth.firebaseapp.com",
projectId: "mrdareauth",
storageBucket: "mrdareauth.appspot.com",
messagingSenderId: "867798194052",
appId: "1:867798194052:web:d1981f8766c25509196fd1",
measurementId: "G-55PP94TD82"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app)
const db = getFirestore(app)
export {auth, db}
Implement features
Now that you have imported the functions and initialized the Firebase services for your app, you can start using them in your React application.
Authentication
To use the authentication service, create a new file called "auth.jsx". The Firebase authentication service provides different ways to authenticate your user but to use the email and password method, import usestate
and useEffect
from React, "auth" from "firebase.jsx", and some relevant authentication functions from the Firebase library. It should look like the code below
import {useState, useEffect} from 'react'
import {auth} from './firebase'
import {createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut} from 'firebase/auth'
After importing the necessary functions you can then go on to write the authentication code which would look like the code below
import {useState, useEffect} from 'react'
import {auth} from './firebase'
import {createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut} from 'firebase/auth'
export const Auth = () => {
const [currentUser, setCurrentUser] = useState('')
useEffect(()=> {
onAuthStateChanged(auth, (user)=> {
if(user){
setCurrentuser(user)
}else {
setCurrentuser(null)
}
})
},[])
const handleSignup = async () => {
try {
const { user } = await createUserWithEmailAndPassword(
auth,
email,
password
)
} catch (error) {
console.log(error)
}
}
const handleLogin = async () => {
try {
const { user } = await signInWithEmailAndPassword(
auth,
email,
password
)
} catch (error) {
console.log(error)
}
}
const logOut = async () => {
await signOut(auth)
setCurrentuser(null)
}
}
In the code above, The useState
hook is used to store the current user, while the useEffect
hook with onAuthStateChanged
listens for changes in the authentication state and allows you to keep track of the current user's authentication status, such as when a user logs in or logs out and it updates the currentUser
state accordingly.
The handleSignup
and handleLogin
functions use the createUserWithEmailAndPassword
and signInWithEmailAndPassword
functions to create new users and sign in existing ones using their email and password.
The auth
provides methods for user authentication and management, such as creating a new user account, signing in with an existing account, and signing out. It is passed as an argument to the onAuthStateChanged
, createUserWithEmailAndPassword
, signInWithEmailAndPassword
, and signOut
methods to perform user authentication and management operations.
The logOut
function uses the signOut
function to sign out the current user and set currentUser
state to null.
Firestore Database
Firestore is a NoSQL database offered by Firebase that allows developers to store and manage data for their web or mobile applications. To use the Firestore database service, create a file called "data.jsx". Import usestate
and useEffect
from React, "db" from "firebase.jsx", and some relevant authentication functions from the Firebase library. It should look like the code below
import {db} from './firebase'
import {addDoc, collection, doc, deleteDoc} from 'firebase/firestore'
After importing the necessary functions you can then go on to write the code to use them to interact with the Firestore database. It should look like the code below
import {db} from './firebase'
import {addDoc, collection, doc, deleteDoc} from 'firebase/firestore'
export const Data = () => {
//function to add a data to firebase database
const handleSubmit = async() => {
try {
await addDoc(collection(db, 'info'), {
name: 'Fran'
age: 21
id: 'vssf2y2fwh2tiuy'
})
}catch (error){
console.log(error)
}
}
//function to delete a data from firebase
const handleDelete = async() => {
try {
await deleteDoc(doc(db, 'info', id)
}catch (error){
console.log(error)
}
}
}
The code above consists of two functions: handleSubmit
and handleDelete
.
handleSubmit
uses the addDoc
function to add a new document to the 'info' collection in the Firestore database. The addDoc
function takes two arguments: the first argument is a reference to a Firestore collection (in this case, 'info'), and the second argument is an object containing the data to be added to the database.
So in this case, the handleSubmit
function is adding a new document with the data: { name: 'Fran', age: 21, id: 'vssf2y2fwh2tiuy' }
to the 'info' collection.
The handleDelete
function on the other hand deletes a document in the collection. It uses the deleteDoc
function to delete a document in the 'info' collection in the Firestore database. the deleteDoc
function takes a doc
reference as its argument. In this case, the reference is created using the doc
function, which takes three arguments: a reference to the Firestore database, the name of the collection (in this case, 'info'), and the id
of the document to be deleted.
Note that there are other things you could also do with the Firestore such as update, as well as listen for real-time updates to your data. You can also use Firestore to query your data, combine and filter data from multiple collections, and perform advanced queries.
Conclusion
In conclusion, this article has covered the basics of building a serverless React application with Firebase. We have seen how Firebase provides us with a powerful suite of tools that allow us to quickly and easily build web applications. However, this is just the beginning, as Firebase offers many other features and services that we have not had a chance to explore in this article. I hope this article has provided a helpful introduction to building serverless React applications with Firebase. Happy coding!