Store and Retrieve Data in Firebase Cloud Storage with React.js
Tags: database, react, firebase, cloud
Published: 2021-09-02 01:38:34


## Introduction 

Cloud computing is the use of a network of remote servers that are hosted on the internet. These remote servers are used to store, manage and process data. The use of cloud will also help companies and developers make systems more secure. Cloud systems enable you to maintain data integrity and data recovery. Developers who don’t use cloud will have less secure software and computer networks that can result in loss of key data.

### Firebase

We will use [Firebase](https://firebase.google.com/) a platform developed by Google for creating mobile and web applications. It was originally an independent company founded in 2011. Its first product was the Firebase Realtime Database, an API that synchronizes application data across iOS, Android, and Web devices, and stores it on Firebase's cloud. The product assists software developers in building real-time, collaborative applications. In October 2017, Firebase has launched Cloud Firestore, a real-time document database as the successor product to the original Firebase Realtime Database

### React

We will use [React](https://reactjs.org/) (also known as React.js or ReactJS) a free and open-source front-end JavaScript library for building user interfaces or UI components. 

## Getting Started
In this tutorial we will be learning how to store and retrieve data in firebase by building a todo-list app.

*Note*
- You should have [Node.js](https://nodejs.org/en/download/) installed on your computer.
- You should have a code editor installed on your computer, I suggest [VS-Code](https://code.visualstudio.com/)
- You should be fairly familiar with React.js and JavaScript

Next thing is creating an empty folder in any directory on your computer preferably Desktop, with a folder name of your choice, in my case **firebase-todos**
Now from your code editor open the folder **firebase-todos** then click on terminal in the vs-code navigations and click on new terminal, before we start running the [Npm CLI-commands](https://docs.npmjs.com/cli/npm/) we first have to check whether Node.js is properly installed by running `node --version` which will show us the version of node successfully installed.

Now let's run our command `npx create-react-app .` with the dot to create the app inside our **firebase-todos** folder. See more about creating [react-app](https://create-react-app.dev/docs/getting-started/)  Now let's start our created app, to do that we run `npm start` in the terminal. Our app should start on `localhost:3000` of our default browser with spinning react icon and a link to learn react. 

It's time to clean up our created app so that the frontend should be what we really want, so let's delete some of the files inside the **src** folder that we don't need.
Let's get rid of the following files
- App.css
- App.test.js
- logo.svg
- reportWebVitals.js
- setupTest.js

Once we delete these file our app will break because in the remaining files, we are trying to read those deleted files, so let go get rid of those lines of codes.
Inside **App.js** file delete the first two lines of code also delete the `header` tag with everything inside it then add a `<h1> hello world </h1>`.
*So `App.js` will no look like this*

```js
function App() {
  return (
    <div className="App">
      <h1>hello world</h1>
    </div>
  );
}

export default App;
 ```

Next, modify the `index.js` file like below:

```js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';


ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
```
When you save, our app would be up again showing just *hello world* in the browser like below.
![hello-world image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgn83efj7oy6ocjba36a.png)

Inside the `src` folder let's create another folder called `Components` and inside `Components` we will create three other files called `Firebase.js`, `Header.js` and `Todos.js`. 

![components-img](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3hsh5im1qqptc9ym9ypv.png)

In `Firebase.js` we will be make communications to firebase, in `Header.js` we will be branding our project and also will be inputing our different todos and from `Todos.js` we will be displaying our todos.

The next thing is setting up firebase firestore in `Firebase.js` file so let's go to [Firebase](https://firebase.google.com/) you need to create an account or sign in if you already have one, then click on the add project card, name your project and click continue, turn off the google analytics and click continue to create your project.
![create-project-img](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c1jo7ej4j9sngt6g8vz.gif)

Next click on the cloud firestore to create firestore database(where we would store our data), click on create database choose either the test or production mode and click next, choose your closest cloud firestore location and click enable, yes we created our firestore database.
![create-firestore-database](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3fhcf4n68s998jrophq.gif)
 
After creating our firestore database the next thing is to create our app, ie IOS, MOBILE OR WEB APP. So click on the setting icon beside the project overview from the dropdown click project setting, choose web application, choose a name for the app and click register app.
![create-app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zyx7shd7l4fnvowuink.gif)

We are almost done with setting up firebase storage, right now we can't store our data in our firestore database because of the store rules, so in the firestore console navigate to rules and allow read, write, and create like below

```js
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read;
      allow create;
      allow request;
      allow update: if false;
    }
  }
}
```
It's time to go back to our code editor but before we proceed we need to copy our firestore database configurations, so click on the setting icon, scroll down and copy everything inside the `script` tag.

Back in your code editor open your terminal and run `npm install firebase` to install firebase then inside the `Firebase.js` file import firebase and paste the configuration you copied from firebase console, then export it by adding the last line of code like below so you would be able to import and use it in another file when you need to. Your `Firebase.js` file should look below

```js
import firebase from "firebase"

// Your web app's Firebase configuration
var firebaseConfig = {
    apiKey: "AIzaSyCceIp****Jp3zbobYqcV_EefHQ0U23J_o",
    authDomain: "todos-31072.firebaseapp.com",
    projectId: "todos-31072",
    storageBucket: "todos-31072.appspot.com",
    messagingSenderId: "494703082670",
    appId: "1:494703082670:web:711****7f533807ebe813f"
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
// export Firebase so it can be used elsewhere 
 const FireBase = firebase.initializeApp(firebaseConfig);
export default Firebase;
```

Next thing, we go into our `Header.js` file and create our frontend layouts, ie the project title and input element to type in our todos and a submit button.

*So let's write these lines on code in our `Header.js`*

```js
import React, { useState } from "react";

function Header() {
  const [input, setInput] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    alert("Hello " + input);
    setInput("");
  };

  return (
    <>
      <center>
        <form onSubmit={handleSubmit}>
          <h1 className="title" style={{ color: "red" }}>
            My Todos
          </h1>
          <div className="input">
            <input
              type="text"
              required
              placeholder="What do you need to do today?"
              value={input}
              onChange={(e) => setInput(e.target.value)}
            />
            <button type="submit">Submit</button>
          </div>
        </form>
      </center>
    </>
  );
}

export default Header;
```
Now import the Header like so `import Header from "./Components/Header";` inside the `App.js` file, get rid of `h1` and it's content then render the `<Header />`.
If you did everything correctly in your browser, it should now look like below

![myTodos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7nq91s8h0hwasip10iup.png)

Everything is working like we wanted, so let's save our input in firestore once we click the submit button instead of alerting *Hello (whatever our input is)*. We will save and get todos from firebase inside the `App.js` file and pass the functions as `props` to each component that needs it. Inside `App.js` let's get our firebase configurations from `Firebase.js` like so `import  FireBase  from "./Components/Firebase";`

The next is to save our input data to firebase collection, so `App.js` will now look like the below:

```js
import React from "react";
import Header from "./Components/Header";
import { v4 as uuid } from "uuid/";
import FireBase from "./Components/Firebase";

function App() {
  const saveTodo = (input) => {
    const saveToFirebase = FireBase.firestore();
    saveToFirebase.collection("todos").add({
      id: uuid(),
      item: input
    });
  };
  return (
    <div className="App">
      <Header saveTodo={saveTodo} />
    </div>
  );
}

export default App;
``` 
Above we created saveTodo function and pass input as it's parameter which will actually come from the input in our `Header.js` file, then called firestore function upon the Firebase configuration we imported from `Firebase.js`, then set our collection id and finally added our object the has an id and item which takes the input parameter.
Also we passed down our saveTodo function to the header component, so inside the `Header.js` we will destructure and pull out the saveTodo function and call it inside the handleSubmit function and pass our actual input as the input parameter it requires. Update the `Header.js` file with the following snippets:

```js
import React, { useState } from "react";

function Header({ saveTodo }) {
  const [input, setInput] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    saveTodo(input);
    setInput("");
  };

  return (
    <>
      <center>
        <form onSubmit={handleSubmit}>
          <h1 className="title">My Todos</h1>
          <div className="input">
            <input
              type="text"
              required
              placeholder="What do you need to do today?"
              value={input}
              onChange={(e) => setInput(e.target.value)}
            />
            <button type="submit">Submit</button>
          </div>
        </form>
      </center>
    </>
  );
}

export default Header;

```
Now whatever you type in as your todo and hit submit, it will be saved in firebase under **todos** collection.
Let's get our todos from firebase, let head back to `App.js` and create a **getTodos function**. First we need to create `todos` state and set it equals to an empty array so in our **getTodos function** we would update the `todos` and set it equals to the data we would get from firebase. we would now pass down the state `todos` to any component that would be needing it, in our case `Todos.js`. *App.js will now look like below*

```js
import React, { useState } from "react";
import Header from "./Components/Header";
import { v4 as uuid } from "uuid/";
import FireBase from "./Components/Firebase";

function App() {
  const [todos, setTodos] = useState([]);

  const saveTodo = (input) => {
    const saveToFirebase = FireBase.firestore();
    saveToFirebase.collection("todos").add({
      id: uuid(),
      item: input,
    });
  };
  const getTodos = () => {
    const getFromFirebase = FireBase.firestore().collection("todos");
    getFromFirebase.onSnapshot((querySnapShot) => {
      const saveFirebaseTodos = [];
      querySnapShot.forEach((doc) => {
        saveFirebaseTodos.push(doc.data());
      });
      setTodos(saveFirebaseTodos);
    });
  };

  return (
    <div className="App">
      <Header saveTodo={saveTodo} getTodos={getTodos} />
    </div>
  );
}

export default App;
```
In the `getTodos()`we targeted our collection *"todos"*, then used firestore's `onSnapShot()` to listen to our document and creates a document snapshot immediately with the current contents, each time the contents change, another call updates the document snapshot, then created an empty array and pushed the data `onSnapShot()` returned and finally set our state `todos` equals to the array.

We will want to call `getTodos()` each time we add a new todo, so we will pass the `getTodo()` to our `Header.js` component, then pull it out in `Header.js` and call it immediately after `saveTodo()` in `handleSubmit()`.

Next, we will call the `getTodos()` once our page loads to have access to previously saved todos and set them equals to our state `todos`, we will do that with the react useEffect hook.
Finally in `App.js`, import and render our `Todos.js` Component and pass down the state `todos` as the Component props. *App.js would finally look like below*

```js
import React, { useState, useEffect } from "react";
import Header from "./Components/Header";
import { v4 as uuid } from "uuid/";
import FireBase from "./Components/Firebase";
import Todos from "./Components/Todos";

function App() {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    getTodos();
  }, []);

  const saveTodo = (input) => {
    const saveToFirebase = FireBase.firestore();
    saveToFirebase.collection("todos").add({
      id: uuid(),
      item: input,
    });
  };
  const getTodos = () => {
    const getFromFirebase = FireBase.firestore().collection("todos");
    getFromFirebase.onSnapshot((querySnapShot) => {
      const saveFirebaseTodos = [];
      querySnapShot.forEach((doc) => {
        saveFirebaseTodos.push(doc.data());
      });
      setTodos(saveFirebaseTodos);
    });
  };

  return (
    <div className="App">
      <Header saveTodo={saveTodo} getTodos={getTodos} />
      <Todos todos={todos} />
    </div>
  );
}

export default App;
```
Next, we head straight to `Todos.js` and pull out the state *todos* we passed down to it from `App.js`, then we map through the *todos* and display each todo in our frontend. *So `Todos.js` will look like below*

```js
import React from "react";

function Todos({ todos }) {
  return (
    <div>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            {todo.item}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default Todos;
```
By now if you did everything correctly you would have your todos displayed in your frontend. Below is my end result
![final result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0u0113wta86wtwy9knp.png)
[Here](https://github.com/Kizmelvin/reactjs-firebase-todos) is the github repository for the code and the styles. Congratulation you have successfully saved and retrieved data in firebase cloud storage.

**Conclusion**

In this Project we built a **Todo App** using React.js and Firebase. With React we created a client that sends data to firebase firestore to store and also a client that consumes the stored data, with Firebase firestore we were able to save the data client provided and give back the said data to the client. For more resources on these tools, visit the documentation of [React](https://reactjs.org/) and [Firebase](https://firebase.google.com/).