{"id":93928,"date":"2022-04-20T19:35:51","date_gmt":"2022-04-20T19:35:51","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=93928"},"modified":"2024-11-18T22:25:14","modified_gmt":"2024-11-18T22:25:14","slug":"working-with-firebase-version-9-modular-sdk-and-react-typescript","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/working-with-firebase-version-9-modular-sdk-and-react-typescript\/","title":{"rendered":"Working with Firebase Version 9 Modular SDK and React Typescript"},"content":{"rendered":"\n<p>\u200b\u200bA common goal in software development is to reduce complexity, and there are measures and software built to help reduce complexity and development time. One of these methods is serverless databases; they provide a database system without creating a server for it, hence the tag \u201cserverless\u201d. Serverless databases help improve productivity and reduce build time, allowing focus on the core functionality of the software.\u200b\u200b<\/p>\n\n\n\n<p>\u200b\u200bThis article builds a simple application utilizing one of these serverless\/cloud-hosted databases. Specifically, it demonstrates integrating Firebase(Modular SDK) Firestore into a React app. To continue with this article, you need to have <a href=\"https:\/\/nodejs.org\/en\/\">node <\/a>installed and basic knowledge of Reactjs and typescript.<\/p>\n\n\n\n<p><a id=\"post-93928-_heading=h.1fob9te\"><\/a> You can find the complete source code in this <a href=\"https:\/\/github.com\/MelvinManni\/firebase_modular_sdk_react\">Github Repo<\/a> and a live version deployed on Netlify<a href=\"https:\/\/unruffled-goldberg-887416.netlify.app\/\"> here<\/a>. The article focuses on the most important parts throughout with the repo filling in any remaining code that\u2019s missing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-what-is-firebase\">What is Firebase?<\/h2>\n\n\n\n<p>\u200b\u200bFirebase is a SaaS platform that provides developers with many services to improve productivity and reduce build time. Firebase is a cloud service backed by Google. Some of the services offered on Firebase are, but are not limited to, authentication, Firestore(cloud\/serverless database), and Realtime database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-firebase-modular-sdk-version-9\"><a id=\"post-93928-_heading=h.3znysh7\"><\/a>\u200b\u200bFirebase Modular SDK (Version 9)<\/h2>\n\n\n\n<p>\u200b\u200bThere was a recent release by Firebase; this current version came with some syntactic changes compared to the previous version. This current version primarily focuses on the modular library, although it still has a compact version with syntax similar to the prior version of Firebase. The modular version of Firebase comes with a couple of advantages, including a reduced app size and split functions to ease the readability of code. One significant difference between version 8 and the recent Modular SDK changes to the API surface is how you use the API changed. Through this article, I will walk you through how to use the new API.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-getting-started-with-the-firebase-modular-sdk-and-react-typescript\"><a id=\"post-93928-_heading=h.2et92p0\"><\/a>\u200b\u200bGetting started with the Firebase Modular SDK and React Typescript<\/h2>\n\n\n\n<p>\u200b\u200bThis article demonstrates building a to-do-list application with authentication. The application will also integrate an avatar image upload using Firebase storage. To get started, create a new react app using the command below.\u200b<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">npx create-react-app firebase9_react \u2013template typescript<\/pre>\n\n\n\n<p>\u200b\u200bAfter creating the React app, you will need to add a few files to the app before continuing. When finished, you should have the files and folders listed below.<\/p>\n\n\n\n<p>\u200b\u200b<img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-93938 size-full\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/files.png\" alt=\"An image showing the Firebase9_react folder directory\" width=\"221\" height=\"710\"><\/p>\n\n\n\n<p>\u200b\u200bThere are two folders and two new files inside the src folder. Start with the \u200b\ud83d\udcdc<em>\u200bFirebase.ts<\/em> file. The <em>Firebase.ts<\/em> file is where you will initialize the Firebase configuration. To set up Firebase, you need to create a new project on the Firebase platform; Head over to <a href=\"https:\/\/firebase.google.com\/\">https:\/\/Firebase.google.com\/ <\/a>and click on the <em>Get Started<\/em> button. Once on the new page, click on <em>Create<\/em> <em>Project<\/em>.\u200b\u200b<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"621\" height=\"303\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/graphical-user-interface-website-description-aut.png\" alt=\"An image showing Welcome to Firebase! Create a Project\" class=\"wp-image-93929\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bEnter the project name and click continue. On the next page, you will choose a Google Analytics account and then click on <em>Create<\/em> <em>project<\/em>; this will take a few seconds to build your project.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"351\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/word-image-10.png\" alt=\"An image showing Configure Google Analytics Create Project\" class=\"wp-image-93930\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bOnce the project build completes, click <em>Continue<\/em>, and on the new page, select web; choose web since you are building a web application. If it were to be an Android or iOS app, you would need to select one of the other options.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"312\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/figreact.png\" alt=\"An image showing Get started by adding Firebase to your app. Select Web\" class=\"wp-image-93939\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bOn the next page, fill in the details for the app. You will be required to enter the application name. Then click on the register; this will take you to the next page with the code block in the image below. The config code block is helpful to initialize Firebase in the react app.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/word-image.jpeg\" alt=\"An image showing the Add Firebase SDK step. Shows install of firebase and sample code\" class=\"wp-image-93932\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bNow that the application is set up, you will need to enable authentication and Firestore for the application. On the sidebar, click on Build to expand the menu; select <em>Authentication<\/em> and enable email and password. If enabling <em>Email\/Password<\/em> is not immediately available, click the <em>Get<\/em> <em>Started<\/em> button to display this option.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"624\" height=\"392\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/word-image-12.png\" alt=\"An image showing the Authentication configuration. Enable Email\/Password\" class=\"wp-image-93933\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bThen head over to <em>Firestore<\/em> <em>Database<\/em> and click on get started; a modal will pop up, asking you to choose the mode you want to begin in. For this article, select <em>test mode.<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"314\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/word-image-13.png\" alt=\"An image showing a dialog asking which mode. Select text mode.\" class=\"wp-image-93934\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bThen click next, select location and voila! Your Firestore is created! You can now get back to the code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-initializing-firebase\"><a id=\"post-93928-_heading=h.tyjcwt\"><\/a>\u200b\u200bInitializing Firebase<\/h2>\n\n\n\n<p>\u200b\u200bHaving set up everything on the Firebase platform, the next course of action will be to install all the dependencies needed for the project. You will need four additional libraries;<\/p>\n\n\n\n<p><strong>\u200b\u200bFirebase<\/strong>: This will give access to the modules needed to access the Firebase API.<\/p>\n\n\n\n<p><strong>\u200b\u200bUUID<\/strong>: This will help generate a unique id for each to-do item<\/p>\n\n\n\n<p><strong>\u200b\u200bstyled-components<\/strong>: the styling library<\/p>\n\n\n\n<p><strong>\u200b\u200breact-router-dom<\/strong>.<\/p>\n\n\n\n<p>\u200b\u200b\u200b\u200bBefore installing the dependencies, specify the post-install script so that typescript knows to install types for the packages. In the <em>package.json<\/em>\u200b file at the end of the scripts block, add the post-install script.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b... \n\u200b\u200b\"scripts\": {\n\u200b\u200b    ...\n\u200b\u200b    \"postinstall\": \"npx typesync\"\n\u200b\u200b  },\n\u200b\u200b...<\/pre>\n\n\n\n<p>\u200b\u200bOnce this is in place, you can install the packages required.\u200b\u200b\u200b\u200b<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">yarn add firebase styled-components uuid react-router-dom<\/pre>\n\n\n\n<p>\u200b\u200bAfter installing the dependencies, head over to the <em>Firebase.ts<\/em>\u200b file and add the configuration from Firebase with a slight adjustment to the code to suit what\u2019s needed.\u200b\u200b<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b\/\/ Import the functions you need from the SDKs you need\nimport { initializeApp } from \"@Firebase\/app\";<br>\u200b\u200bimport { getAuth } from \"@Firebase\/auth\";\n\u200b\u200bimport { getFirestore } from \"@Firebase\/firestore\";\nimport { getStorage } from \"@Firebase\/storage\";\n\/\/ TODO: Add SDKs for Firebase products that you want to use\n\u200b\u200b\/\/ https:\/\/Firebase.google.com\/docs\/web\/setup#available-libraries\n\u200b\u200b\/\/ Your web app's Firebase configuration\n\u200b\u200b\/\/ For Firebase JS SDK v7.20.0 and later, measurementId is optional\n\u200b\u200bconst FirebaseConfig = {\n\u200b\u200b  apiKey: \"AIzaSyA7WcmtmOBmlUDLLFYEzd-B6ksVD8K_8pU\",\n\u200b\u200b  authDomain: \"fir-react-16b4d.Firebaseapp.com\",\n  projectId: \"fir-react-16b4d\",\n\u200b\u200b  storageBucket: \"fir-react-16b4d.appspot.com\",\n  messagingSenderId: \"457263847185\",\n\u200b\u200b  appId: \"1:457263847185:web:d20095f49f62344b9f5eb0\",\n  measurementId: \"G-67NB340CQE\",\n};\n\u200b\u200b\/\/ Initialize Firebase\n\u200b\u200bconst app = initializeApp(FirebaseConfig);\n\u200b\u200bexport const auth = getAuth(app);\n\u200b\u200bexport const db = getFirestore(app);\n\u200b\u200bexport const storage = getStorage(app);\n<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200bThe code on line 20 initializes the Firebase app with the configuration file from the Firebase platform; this serves as an identifier for the project and allows access to Firebase services. Due to the modular SDK update, Firebase made it import each Firebase service as a stand-alone sub-package. On line 21, the code assigns the authentication subpackage to the auth variable and subsequent action for the rest of the services used for this article.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-setting-up-the-context-for-managing-authentication\"><a id=\"post-93928-_heading=h.3dy6vkm\"><\/a>\u200b\u200bSetting up the context for managing authentication<\/h2>\n\n\n\n<p>\u200b\u200bIn this section, you will set up the context API for state management. In the <em>AppContext.tsx\u200b<\/em> file, set up all Firebase functionalities for the application.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200bimport React, { ReactElement } from \"react\";\n\u200b\u200bimport {\n\u200b\u200b  createUserWithEmailAndPassword,\n\u200b\u200b  onAuthStateChanged,\n\u200b\u200b  signInWithEmailAndPassword,\n\u200b\u200b  signOut,\n\u200b\u200b  updateProfile,\n\u200b\u200b} from \"@Firebase\/auth\";\n\u200b\u200bimport { ref, uploadBytes, getDownloadURL } from \"@Firebase\/storage\";\n\u200b\u200bimport { query, where, collection, getDocs, doc, setDoc, deleteDoc, updateDoc } from \"@Firebase\/firestore\";\n\u200b\u200bimport { auth, db, storage } from \".\/Firebase\";\n\u200b\u200bimport { v4 as uuid } from \"uuid\";\n\u200b\u200b...\n\u200b\u200bexport const AppContext = React.createContext&lt;contextTypes&gt;(contextDefaultVal);\n\u200b\u200bexport default function AppContextProvider({ children }: Props): ReactElement {\n\u200b\u200b  const [currentUser, setCurrentUser] = React.useState&lt;userTypes | null&gt;(null);\n\u200b\u200b  const [loading, setLoading] = React.useState(false);\n\u200b\u200b  const [todoItems, setTodoItems] = React.useState&lt;todoItemInterface[]&gt;([]);\n\u200b\u200b  ...\n\u200b\u200b  return (\n\u200b\u200b    &lt;AppContext.Provider\n\u200b\u200b      value={{\n\u200b\u200b        loading,\n\u200b\u200b        currentUser,\n\u200b\u200b        todoItems,\n\u200b\u200b        logInUser,\n\u200b\u200b        registerUser,\n\u200b\u200b        handleAuthChange,\n\u200b\u200b        updateAvatar,\n\u200b\u200b        addTodoItem,\n\u200b\u200b        getTodoItems,\n\u200b\u200b        updateTodoItem,\n\u200b\u200b        deleteTodoItem,\n\u200b\u200b        signOutUser,\n\u200b\u200b      }}\n\u200b\u200b    &gt;\n\u200b\u200b      {children}\n\u200b\u200b    &lt;\/AppContext.Provider&gt;\n\u200b\u200b  );\n\u200b\u200b}<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200b<a id=\"post-93928-_heading=h.1t3h5sf\"><\/a>\u200b\u200bApplication Functionalities<\/p>\n\n\n\n<p>The following sections cover the AppContext in bits. If you look at the value object passed to the provider, you see the loading state for Login and registering a user, the to-do items, and other functions for authentications and CRUD operation. These are the functions that you\u2019ll use in the React application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-authentication-with-firebase-auth\"><a id=\"post-93928-_heading=h.4d34og8\"><\/a>\u200b\u200bAuthentication with Firebase auth<\/h3>\n\n\n\n<p>\u200b\u200bThe application has a register page and login page; the design of the registration page looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"1280\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/04\/word-image-14.png\" alt=\"An image showing the registration page\" class=\"wp-image-93935\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>\u200b\u200bThree inputs are required to successfully register on the application. The values from the input fields will be passed into the <code>registerUser<\/code>\u200b function below:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200binterface registrationTypes {\n\u200b\u200b  displayName: string;\n\u200b\u200b  email: string;\n\u200b\u200b  password: string;\n\u200b\u200b}\n\u200b\u200b...\n\u200b\u200bconst registerUser = async (data: registrationTypes) =&gt; {\n\u200b\u200b    setLoading(true);\n\u200b\u200b    try {\n\u200b\u200b      await createUserWithEmailAndPassword(auth, data.email, data.password).then(async ({ user }) =&gt; {\n\u200b\u200b        await updateProfile(user, {\n\u200b\u200b          displayName: data.displayName,\n\u200b\u200b        });\n\u200b\u200b      });\n\u200b\u200b    } catch (error) {\n\u200b\u200b      alert(error);\n\u200b\u200b    } finally {\n\u200b\u200b      setLoading(false);\n\u200b\u200b    }\n\u200b\u200b  };\n\u200b\u200b...<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200bThe function above accepts three values: the <code>displayName<\/code>, <code>email<\/code> and <code>password<\/code>. In line 11, the code creates a new user using the <code>createUserWithEmailAndPassword<\/code>\u200b function from Firebase; this function takes in three values: the Firebase auth identifier created in the <em>Firebase.ts\u200b<\/em> file, the email, and password of the new user. Once a user is registered, it updates the displayName with the value passed into the function. Next up, you will be handling the Login for created users. Similar to the Registration page, there is a form with two inputs for email and address. The values from these input fields will be passed to the <code>loginUser<\/code>\u200b function on submit.\u200b\u200b<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200b   const logInUser = async (email: string, password: string) =&gt; {\n\u200b\u200b    setLoading(true);\n\u200b\u200b    try {\n\u200b\u200b      await signInWithEmailAndPassword(auth, email, password);\n\u200b\u200b    } catch (error) {\n\u200b\u200b      alert(error);\n\u200b\u200b    } finally {\n\u200b\u200b      setLoading(false);\n\u200b\u200b    }\n\u200b\u200b  };\n\u200b\u200b...<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200bThe <code>logInUser<\/code>\u200b function will pass the email and password to the <code>signInWithEmailAndPassword<\/code>\u200b function provided by Firebase.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-handling-profile-image-upload\">\u200b\u200bHandling profile image upload<\/h3>\n\n\n\n<p>\u200b\u200bOnce authenticated, a user will have access to the home page, where they can preview all their to-do items and profile information. The <em>Home.tsx<\/em>\u200b code has an input tag for handling file upload.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200bexport default function Home(): ReactElement {\n  const history = useHistory();\n\u200b\u200b  const [value, setValue] = React.useState&lt;string&gt;(\"\");\n  const { addTodoItem, getTodoItems, todoItems, currentUser, handleAuthChange, signOutUser, updateAvatar } =\n\u200b\u200b    React.useContext(AppContext);\n\u200b\u200b...\n\u200b\u200b  const handleImageChange = async (e: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; {\n    if (e.target.files !== null &amp;&amp; e.target.files.length &gt; 0) {\n\u200b\u200b      const rawImage = e.target.files[0];\n\u200b\u200b      \/\/ fetches the extension name of the image\n      \/\/ gets the last index of the '.' and adds 1 to it\n\u200b\u200b      \/\/ returns a substring of all character to the left after this index\n      const ext = rawImage.name.substr(rawImage.name.lastIndexOf(\".\") + 1);\n      const image = new Blob([rawImage], { type: \"image\" });\n      updateAvatar({ image, ext });\n\u200b\u200b    }\n  };\n\u200b\u200b...\n}\n<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200bThe <code>handleImageChange<\/code>\u200b controls the <code>onChange<\/code> event for the file input. A substring of the file name from the last \u201c.\u201d in the string is in line 14; thus, it only extracts the extension name from the string. Then the <code>rawImage<\/code> is converted to a Blob and the image Blob and extension name are passed to the <code>updateAvatar<\/code>\u200b function.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200b  const updateAvatar = async (file: { image: Blob; ext: string }) =&gt; {\n\u200b\u200b    try {\n\u200b\u200b      if (auth.currentUser !== null) {\n        \/\/File reference\n\u200b\u200b        const uploadRef = ref(storage, `profileImages\/${auth.currentUser.uid}-${uuid()}.${file.ext}`);\n        const avatarRef = await uploadBytes(uploadRef, file.image);\n\u200b\u200b        \/\/ get the file url from Firebase stoprage\n\u200b\u200b        const image = await getDownloadURL(avatarRef.ref);\n\u200b\u200b        \/\/ Update users photoURL\n\u200b\u200b        await updateProfile(auth.currentUser, {\n\u200b\u200b          photoURL: image,\n\u200b\u200b        });\n\u200b\u200b        alert(\"Profile image updated\");\n        \/\/ Reload the current user to fetch new profileUrl\n\u200b\u200b        await auth.currentUser.reload();\n      }\n\u200b\u200b    } catch (error) {\n\u200b\u200b      alert(error);\n\u200b\u200b    }\n  };\n\u200b\u200b...\n<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200bThe <code>updateAvatar<\/code>\u200b function takes the Firebase storage identifier declared in the Firebase configuration file and a reference for the file to upload. Once the upload request completes, the code calls the <code>getDownloadURL<\/code>\u200b function with the uploaded file ref. The <code>getDownloadURL<\/code>\u200b function converts the file ref to a URL that will access the image uploaded. Finally, the URL is passed to the <code>photoURL<\/code> key on the user object. Once complete, the user details are reloaded [Line 16] to reflect the changes made to the user object.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-creating-a-new-to-do-item\"><a id=\"post-93928-_heading=h.17dp8vu\"><\/a>\u200b\u200bCreating a new to-do item<\/h3>\n\n\n\n<p>\u200b\u200bTo create a new to-do item, you need to pass in the value of the new item. The <code>addTodoItem<\/code>\u200b function accepts this new value, and creates a new document on Firestore.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200bconst addTodoItem = async (value: string) =&gt; {\n\u200b\u200b    try {\n      \/\/ document reference to be added\n      const docRef = doc(\n\u200b\u200b        db,\n\u200b\u200b        \"todo\",\n\u200b\u200b        uuid() \/*unique id for new document, Note that firestore can do this for you if you leave the third parameter empty*\/\n\u200b\u200b      );\n\u200b\u200b      const userId = auth.currentUser;\n      if (userId !== null) {\n        await setDoc(docRef, {\n\u200b\u200b          userId: userId.uid,\n          value,\n        });\n\u200b\u200b        alert(`Item ${value} added!`);\n\u200b\u200b      }\n\u200b\u200b    } catch (error) {\n\u200b\u200b      alert(error);\n\u200b\u200b    }\n\u200b\u200b  };\n...\n<\/pre>\n\n\n\n<p>\u200b\u200b\u200b\u200bThe <code>addTodoItem<\/code>\u200b creates a ref for the document to be uploaded using the <code>doc<\/code>\u200b function. The first parameter needs to be the identifier for Firestore declared in the Firebase configuration file. You pass in the collection for the document, and finally, the document id. Firebase, by default, generates a unique id for the document, but I\u2019ve decided to use uuid to create the document id. To conclude the document creation, you need to call the setDoc\u200b function provided by Firebase and pass in the docRef\u200b and the new document object as a second parameter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-reading-to-do-items-from-firestore\"><a id=\"post-93928-_heading=h.3rdcrjn\"><\/a>\u200b\u200bReading to-do items from Firestore<\/h3>\n\n\n\n<p>\u200b\u200bNext up is reading the documents on Firestore. To accomplish this, you will be using the <code>getDocs<\/code>\u200b function from Firebase. The <code>getDocs<\/code>\u200b function accepts a query of the document\/documents needed. To get only one document, use the <code>getDoc<\/code>\u200b. In the <code>getTodoItems<\/code> function, you will get all documents where the <code>userId<\/code> matches the user&#8217;s uid of the user currently logged in and assign it to the <code>querySnapshot<\/code>\u200b variable.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200b  const getTodoItems = async () =&gt; {\n    try {\n      if (auth.currentUser !== null) {\n\u200b\u200b        const userId = auth.currentUser.uid;\n        \/\/ query to get only the documents that matches logged in user id\n\u200b\u200b        const q = query(collection(db, \"todo\"), where(\"userId\", \"==\", userId));\n       const querySnapshot = await getDocs(q);\n        \/\/ reset the todo items value\n\u200b\u200b        setTodoItems([]);\n\u200b\u200b        \/\/ map through the query result and assign the value to the todoItems state\n        querySnapshot.forEach((doc) =&gt; {\n          const data = doc.data();\n          setTodoItems((prev) =&gt; [\n\u200b\u200b            ...prev,\n            {\n\u200b\u200b              itemId: doc.id,\n\u200b\u200b              value: data.value,\n            },\n          ]);\n        });\n\u200b\u200b      }\n\u200b\u200b    } catch (error) {\n\u200b\u200b      alert(error);\n    }\n\u200b\u200b  };\n\u200b\u200b...\n<\/pre>\n\n\n\n<p>\u200b\u200bWhen the request to fetch the data concludes, you map through the documents and set each document&#8217;s value and document id to <code>todoItems<\/code>\u200b state.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-updating-already-existing-to-do-item\"><a id=\"post-93928-_heading=h.26in1rg\"><\/a>\u200b\u200bUpdating already existing to-do item<\/h3>\n\n\n\n<p>\u200b\u200bThis is similar to creating a document except that you pass in a query and the value to update. The document matching the reference passed in will be mutated. The <code>updateDoc<\/code>\u200b function from Firebase updates records\/documents.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">... \nconst updateTodoItem = async (params: { newValue: string; id: string }) =&gt; {\n    try {\n\u200b\u200b      \/\/ reference to the document to update\n      const docRef = doc(db, \"todo\", params.id);\n\u200b\u200b      \/\/ Update the value of the todo item\n      await updateDoc(docRef, {\n\u200b\u200b        value: params.newValue,\n\u200b\u200b      });\n\u200b\u200b      alert(`Item updated!`);\n\u200b\u200b    } catch (error) {\n\u200b\u200b      alert(error);\n\u200b\u200b    }\n\u200b\u200b  };\n...\n<\/pre>\n\n\n\n<p>\u200b\u200bThe <code>updateTodoItem<\/code>\u200b function accepts two parameters, the new value and the document id, to update. The document reference receives the id, and <code>updateDoc<\/code>\u200b accepts the value as a second parameter. \u200b\u200b<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-deleting-a-to-do-item\"><a id=\"post-93928-_heading=h.lnxbz9\"><\/a>\u200b\u200bDeleting a to-do item<\/h3>\n\n\n\n<p>\u200b\u200bTo complete a CRUD operation, you need to delete a to-do item; this is a straightforward action. You need to create a reference to the document you want to delete and pass this reference into the <code>deleteDoc<\/code>\u200b function from Firestore. This action will trigger a delete on the document matching the reference.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u200b\u200b...\n\u200b\u200bconst deleteTodoItem = async (id: string) =&gt; {\n\u200b\u200b    try {\n\u200b\u200b      \/\/ reference to the document to delete\n      const docRef = doc(db, \"todo\", id);\n\u200b\u200b      await deleteDoc(docRef);\n      alert(`item: ${id} deleted!`);\n    } catch (error) {\n      alert(error);\n    }\n  };\n...\n<\/pre>\n\n\n\n<p>\u200b\u200bSubsequently, you will look at one more function from Firebase; this is the <code>onAuthStateChanged<\/code>\u200b function. The <code>onAuthStateChanged<\/code>\u200b is an event listener that checks if a user is authenticated. It accepts two parameters: the auth identifier and a call back function with the user object as a parameter. If the user object is null, there is no user in session\/currently logged in; otherwise, it will return the user object.\u200b\u200b<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-deploying-the-application\"><a id=\"post-93928-_heading=h.35nkun2\"><\/a>\u200b\u200bDeploying the application<\/h3>\n\n\n\n<p>\u200b\u200bTo deploy your application, you can run yarn build and deploy your built application on any platform of your choice. You can also deploy and host your application with Firebase. You can learn all about that <a href=\"https:\/\/firebase.google.com\/docs\/hosting\/quickstart\">here. <\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-conclusion\"><a id=\"post-93928-_heading=h.1ksv4uv\"><\/a>\u200b\u200bConclusion<\/h2>\n\n\n\n<p>\u200b\u200bThis article covered how to handle authentication, use the storage, and perform crud operation on the Firestore using the Firebase Modular SDK. For additional information on the extensive use of Firebase, you can check out the <a href=\"https:\/\/firebase.google.com\/docs\">official documentation.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Firebase is a SaaS platform that provides developers with many services to improve productivity and reduce build time. In this article, Goodness Woke demonstrates working with Firebase Version 9 and React Typescript.&hellip;<\/p>\n","protected":false},"author":339480,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143526,53],"tags":[95506],"coauthors":[145948],"class_list":["post-93928","post","type-post","status-publish","format-standard","hentry","category-development","category-featured","tag-automate"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/93928","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/339480"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=93928"}],"version-history":[{"count":9,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/93928\/revisions"}],"predecessor-version":[{"id":104608,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/93928\/revisions\/104608"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=93928"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=93928"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=93928"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=93928"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}