Skip to content

Exercise 09 : Firebase Todo App

Introduction

You will create a small Todo React application which uses Firebase to store todo's.

Image 01

Create a new project

Create a new React firebase-todo-app project and install Firebase library to your project.

1
2
npx create-react-app firebase-todo-app
npm install firebase

Follow earlier made exercise to build your app

Follow Exercise 02 to create a the main building blocks of your Todo application. Just copy/replace todo App.js and App.css files.

Setting Up Firebase

Firebase is Google’s mobile/web platform that helps you quickly develop high-quality apps and grow your business. Go to Firebase homepage and click on the Get started button and Create a new Todo project.

Image 02

You can enable (or not) Google Analytics for your Firebase project. Google Analytics is a free and unlimited analytics solution that enables targeting, reporting and more in Firebase Crashlytics, Cloud Messaging, In-App Messaging, Remote Config, A/B Testing, Predictions and Cloud Functions.

Image 03

Choose or create a Google Analytics account used with this app.

Image 04

Your project should be now ready for development.

Image 05

Add a Database

Configure Firebase realtime database for your Todo App. Click on Cloud Firestore badge or select Database in left side menu. Click Create database button.

Image 06

Select the “Start in test mode” option and click on the next button. Now you are developing your application, so you should start in test mode. Test mode lets anyone, with or without authentication, read and write to your database. Although this mode is good for developing and debugging, you should always change to production mode when you’re ready for production.

Image 07

A final step is to specify Cloud Firestore location. You should select some location from Europe.

Image 08

Finally your database is ready to use.

Image 09

Add a sample data

Your Todo database should be selected by default if not, just select it and add a collection for a Todo items. Select the + Start collection option, and create a name for collection. As highlighted in the tooltip, a collection is a set of documents, which contain a data. Add todos as a collection ID.

Image 10

Add a sample data to the database. Use text as a Field name, and string as a Type. Type some Value and save sample data. Remember add/click auto id for your field.

Image 11

You can add a more Todo sample data items to database using + Add document option. Remember use text as a field name and string as a Type.

Each Todo item is a document in a database.

Image 12

Connect React app to Firebase project

In Firebase Todo project’s homepage, you will notice five (or more) circular icons (click + Add app button). Click web icon to create a web application.

Image 13

Click on it, register your app.

Image 14

Note apiKey, authDomain, databaseURL, projectId, storageBucket, messagingSenderId, appId and measurementId values. These values are unique for each user’s each project.

Image 15

Add a given code to your App.js and continue back to the console.

Note

You can find more information about firebase programming here:

Load sample data

Load sample Todo items using React Hooks. Import useEffect and useState. Import firebase functions and use your own configuration in App.js.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import React, { useEffect, useState } from 'react';
import { initializeApp } from 'firebase/app';
import { 
  getFirestore, 
  collection, 
  getDocs, 
  setDoc, 
  addDoc, 
  deleteDoc, 
  doc 
} from 'firebase/firestore/lite';

// TODO: Replace the following with your app's Firebase project configuration
const firebaseConfig = {
  //...
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

Modify your App to load Todo items from the Firebase in ToDoFormAndList function. You can use useEffect to fetch data from the database.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
function ToDoFormAndList() {
  // ...
  // data is loading
  const [loading, setLoading] = useState(true);

  // load todo list items
  useEffect(() => {
    const fetchData = async () => {
      // connect todos collection
      const todosCol = collection(db, 'todos');
      const todoSnapshot = await getDocs(todosCol);
      // todo text and id 
      // document id is unique, so it can be used with deleting todo
      const todos = todoSnapshot.docs.map(doc => {
        return  { 
          text: doc.data().text,
          id: doc.id 
        };
      });
      // set states
      console.log(todos);
      setItems(todos);
      setLoading(false);
    }
    // start loading data
    console.log("fetch data...")
    fetchData();
  },[]); // called only once

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type='text' value={itemText} onChange={event => setItemText(event.target.value)} placeholder="Write a new todo here" />
        <input type='submit' value='Add'/>
      </form>
      <ul>
      { loading  && 
        <p>Loading...</p>
      }
      {items.map(item => (
        <li key={item.id}>
          {item.text+" "} <span onClick={() => removeItem(item)}> x </span>
        </li>
      ))}
    </ul>    
    </div>
  )  

// ...
}

Note

Remember test your application

Add a new todo

Modify handleSubmit function to create a new todo item. A new item will be created and added to the database. Database call will return added item to document. This document id will be stored to todo item, so it can be deleted later.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// add todo
const handleSubmit = async (event) => {
  // prevent normal submit event
  event.preventDefault();
  // add item to Firebase
  let newItem =  { text: itemText };
  const docRef = await addDoc(collection(db, "todos"), newItem);
  // get added doc id and set id to newItem
  newItem.id = docRef.id;
  // update states in App
  setItems( [...items, newItem]);
  // modify newItem text to ""
  setItemText("")
}

Remove a todo

Modify removeItem function to use todo item as a parameter. Remember change it from the calling code too (now item id was used in earlier version). First delete item from the database and then from the items state list.

1
2
3
4
5
6
7
const removeItem = (item) => {
  // delete from firebase
  deleteDoc(doc(db, "todos", item.id));
  // delete from items state and update state
  let filteredArray = items.filter(collectionItem => collectionItem.id !== item.id);
  setItems(filteredArray); 
}

Test and run

Save your application. Now it should work. Refresh your browser and you should see that it keeps state. Earlier version doesn't save Todos.

Authentication

Follow Firebase documentation - auth and modify your application to use for example email/password authentication.

  • Add one test account to Firebase
  • Show a login dialog when application starts (use React Router)

Image 16

  • Show todos after successfull login and create logout functionality

Image 17

Test

Test your application and use some different styles (etc.. colors) in your application UI.

Push exercise 09 / Firebase Todo App to GitLab

Test your application in web browser, take screenshots and commit/push your project and screenshots back to JAMKIT/GitLab. Remember move your exercise/issue ticket from Doing to In Review in Issues Board and write your learning comments to issue comments.

Save screenshots to firebase-todo-app folder.