CRUD operation on Firebase Realtime database

Hey! developers let’s develope a basic MyAnimeList in which we will be working from scratch like creating react app to firebase setup and crud operations on it.
STEP-1
Let’s create a react app
In your cmd write

npx create-react-app MyAnimeList
cd My…


This content originally appeared on DEV Community and was authored by Kirti

Hey! developers let's develope a basic MyAnimeList in which we will be working from scratch like creating react app to firebase setup and crud operations on it.
STEP-1
Let's create a react app
In your cmd write

npx create-react-app MyAnimeList
cd MyAnimeList
npm start

STEP-2
Lets setup firebase for our MyAnimeList
a. google firebase console and login with your Gmail account
b. On the top right corner you will see go to console click on it and there you will see add project button click on add project.
c. Fill in the steps
i. Enter your project name(MyAnimeList)
ii. Toggle the button (off) google analytics for firebase
project.
iii. click on create project now.
Wow! you just created your project on firebase now let's add firebase to our webApp.
Below the name of your webApp you will see a symbol "</>" click on it and add name in it and click on Also set up Firebase Hosting for this app.
Now click on register app.
You will get firebase configuration here copy it we will use it later.

step -3
Install firebase for app

npm install firebase

Now create a file in your src and name it as firebase.js
Now paste it here the code that we copied above, and create an const variable to initialize firebase and after initializing export it. Have a look at the code below.

import firebase from 'firebase/compat/app';
import 'firebase/compat/database';

var firebaseConfig = {
    apiKey: "AIzaSyDowJOJykSjXj5tbwybpinypYh7UGV9YGc",
    authDomain: "myanimelist-e637e.firebaseapp.com",
    databaseURL: "https://myanimelist-e637e-default-rtdb.firebaseio.com",
    projectId: "myanimelist-e637e",
    storageBucket: "myanimelist-e637e.appspot.com",
    messagingSenderId: "854247297412",
    appId: "1:854247297412:web:4c977510e0f36b54220dd1"
  };

const fireDb = firebase.initializeApp(firebaseConfig);
export default fireDb.database().ref();

Now, go to console and click on Realtime database and create database choose or leave the location as it and click on start in test mode and enable it.
yippee... we did all the setup part now let's move forward and create our app.
Lets start our app with building the navbar component.
Firstly we would need to install react-router-Dom library for routing it to multiple pages and we can achieve it with browser stack , switch and route. I also installed toastify for styling.
In app.js
In navbar we have a logo at the left and in right we have pages
before jumping it here do create a sperate folder named pages and create all the .js files for the pages on which we will be working on later and import it here in the app.js.

import React from "react"
import './App.css';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import About from './pages/About';
import Add from './pages/Add';
import Home from './pages/Home';
import View from './pages/View';
import Navbar from "./Components/Navbar";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
function App() {
  return (
    <BrowserRouter>

      <div className="App">
        {/* calling our navbar component where actual logic is there */}
      <Navbar/>
        <ToastContainer position="top-center" />
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/add" component={Add} />
           {/* We need an id of the particluar anime which we want to update  and view */}
          <Route path="/update/:id" component={Add} />
          <Route path="/view/:id" component={View} />
          <Route path="/about" component={About} />
        </Switch>
      </div>
    </BrowserRouter>
  );
}
export default App;

Now lets work on our navbar component which we imported in our app.js here we are going to use react-hooks like useState and useEffect. We also need link and uselocation from react-router-dom we are using useLocation because we want to highlight that tab of navbar which we are currently on even if visit diffrent pages with our URL.
I have added proper explanation of each line of the code in the code itself.

import React, { useEffect, useState } from 'react';
import { Link, useLocation } from 'react-router-dom';
import "./Navbar.css";

const Navbar = () => {
    const [activeTab, setActiveTab] = useState("Home");
     //it gives the location that where we are currently
    const location = useLocation();
   // a useeffect hook to active the tab of particular pathname
    useEffect(() => {
        if (location.pathname === '/')
            setActiveTab("Home")
        else if (location.pathname === '/add')
            setActiveTab("Add")
        else if (location.pathname === '/about')
            setActiveTab("About")
    }, [location]); // we passed location here because we want this hook to work only if there is change in location

    return (
        <div className="header">
            <p className="logo">Otaku</p>
            <div className="header-right">
                <Link to="/">
                    <p className={`${activeTab === "Home" ? "active" : ""}`}
                        onClick={() => setActiveTab("Home")}
                    >
                        Home
                    </p>
                </Link>

                <Link to="/add">
                    <p className={`${activeTab === "Add" ? "active" : ""}`}
                        onClick={() => setActiveTab("Add")}
                    >
                        Add
                    </p>
                </Link>

                <Link to="/about">
                    <p className={`${activeTab === "About" ? "active" : ""}`}
                        onClick={() => setActiveTab("About")}
                    >
                        About
                    </p>
                </Link>
            </div>
        </div>
    );
};

export default Navbar;

Now some styling of Navbar just copy paste the CSS file or design it in your own way not a big fan of CSS!!

.header
{
    overflow: hidden;
    background: linear-gradient(to bottom, black 0%, #497BE8 35%, grey 55%);
}
.header p{
    float: left;
    color: black;
    text-align: center;
    padding: 10px;
    text-decoration: none;
    font-size: 18px;
    line-height: 5px;
    font-weight: bold;
    font-family: cursive;
    border-radius: 2px;
}
.header p.logo
{
    font-size: 25px;
    font-weight: bold;
    color: black;
    font-family: cursive;
}
.header p:hover{
    background-color: black;
    color: grey;
}

.header p.active{
    background-color: indigo;
    color: pink;
}

.header-right
{
    float: right;
}

@media screen and (max-width: 500px)
{
    .header p {
        float: none;
        display: block;
        text-align: left;
    }

    .header-right {
        float: none;
    }
}

Yippeee done with navbar!!
Now let's Move to our next part where we will be creating Add page in which we will be taking users input and pushing it into the database. I Have added the explanation of the lines wherever needed and have also validated the form as you cannot submit empty form.

import React, { useState, useEffect } from 'react';
import fireDb from '../firebase';
import { toast } from 'react-toastify';
import { useHistory } from 'react-router';
import "./Add.css"

const intialstate = {
    name: "",
    genre: "",
    myPersonalRating: ""
}

const Add = () => {
    const [state, setState] = useState(intialstate);
    const { name, genre, myPersonalRating } = state;

    const history = useHistory();

    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setState({ ...state, [name]: value });
    };
    // here is handlesubmit function where an event is passed
    const handleSubmit = (e) => {
        e.preventDefault();
        // validating if any of the fields is emepty than show an error with the use of toastify
        if (!name || !genre || !myPersonalRating) {
            toast.error("All Fields are mandatory")
        }
        else {
            // imp part to push the values in the database with checking the error also if not than display success
            fireDb.child("Anime").push(state, (err) => {
                if (err) {
                    toast.error(err);
                }
                else {
                    toast.success("Added Successfully")
                }
            });
            // here we are adding a delay of 5 sec and than redirectig it to home page after adding 
            setTimeout(() => history.push("/"), 500);
        }
    };
   // below is the form implementation of the three input fields which we are asking from the user
    return (
        <div style={{ marginTop: "100px" }}>
            <form style={{ margin: "auto", padding: "15px", maxWidth: "400px", alignContent: "center" ,
            color: "brown"}}
                onSubmit={handleSubmit}> 
                <label htmlFor="name">Anime Name</label>
                <input type="text" id="name"
                    name="name"
                    placeholder="Anime Name"
                    value={name}
                    onChange={handleInputChange} />

                <label htmlFor="genre">Genre</label>
                <input type="text" id="genre"
                    name="genre"
                    placeholder="Anime genre"
                    value={genre}
                    onChange={handleInputChange} />

                <label htmlFor="MyPersonalRating">MyPersonalRating</label>
                <input type="number" id="myPersonalRating"
                    name="myPersonalRating"
                    placeholder="Rate It"
                    value={myPersonalRating}
                    onChange={handleInputChange} />

                <input type="submit" value='save'  />
            </form>
        </div>
    )
}
export default Add       

It's CSS code

input[type="text"],
input[type="email"],
input[type="number"],
select {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display: inline-block;
    border: 1px solid #ccc;
    border-radius: 4px;
    text-align: center;
    font-family: fantasy;
    box-sizing: border-box;
    border-radius: 6px;
}
 input[type="submit"] {
     width: 100%;
     background-color: darkgreen;
     color: white;
     padding: 14px 20px;
     margin: 8px 0;
     border: none;
     border-radius: 4px;
     cursor: pointer;
 }
input[type="submit"]:hover {
    background-color: darkgreen;
}

Done with adding it into database now lets display it in tabular form in our home page.

import { useEffect, useState } from "react"
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import fireDb from '../firebase';
import "./Home.css";

const Home = () => {

    const [data, setData] = useState({});

    const onDelete = (id) =>{
        if(window.confirm("Are you sure you want to delete it ?"))
        {
            fireDb.child(`Anime/${id}`).remove((err) =>{
                if(err)
                {
                    toast.error(err);
                }
                else 
                {
                    toast.success("deleting from the database");
                }
            })
        }
    }

    useEffect(() => {
        fireDb.child("Anime").on("value",(snapshot) => {
            if(snapshot.val() !== null)
            {
                setData({...snapshot.val()});
            }
            else
            {
                setData({});
            }
        });
        return () => {
            setData({});
        };
    },[]);

    return (
        <div style={{ marginTop: "100px"}}>
            <table className="styled-table">
                <thead>
                    <tr>
                        <th style={{ textAlign: "center" }}> No</th>
                        <th style={{ textAlign: "center" }}> Name</th>
                        <th style={{ textAlign: "center" }}> Genere</th>
                        <th style={{ textAlign: "center" }}> MyPersonalRating</th>
                        <th style={{ textAlign: "center" }}> Action</th>
                    </tr>
                </thead>
                <tbody>
                    {/* maping the objects we have in database */}
                    {
                        Object.keys(data).map((id, index) => {
                            return (
                                    <tr key={id}>
                                        <th scope="row">
                                            {index+1}
                                        </th>
                                        <td>{data[id].name}</td>
                                        <td>{data[id].genre}</td>
                                        <td>{data[id].myPersonalRating}</td>
                                        <td>
                                            <Link to ={`/update/${id}`}>
                                                <button className="btn btn-edit">Edit</button>
                                            </Link>
                                                <button className="btn btn-delete" onClick={()=> onDelete(id)}>Delete</button>

                                            <Link to ={`/view/${id}`}>
                                                <button className="btn btn-view">View</button>
                                            </Link>
                                            </td>
                                    </tr>
                            );
                        }
                        )
                    }
                </tbody>
            </table>

        </div>
    )
}
export default Home;

It's CSS file

.styled-table{
    border-collapse:collapse;
    margin: auto;
    font-size: 0.9em;
    font-family: sans-serif;
    max-width: 800px;
    box-shadow: 0 0 20px rgba(0,0,0,0.15);
    align-content: center;
}

.styled-table thead tr {
    background-color: darkslategray;
    color: deepskyblue;
    text-align: left;
}

.styled-table th,
.styled-table td{
    padding: 12px 15px;
}

.styled-table tbody tr {
    border-bottom: 1px solid #dddd;
}

.styled-table tbody tr:nth-of-type(even)
{
    background-color: dimgrey;
}

.styled-table tbody tr:last-of-type{
    border-bottom: 2px solid #009879;
}

.btn {
    border: none;
    color: white;
    padding: 5px 8px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    border-radius: 5px;
    font-size: 16px;
    margin: 4px 2px;
    cursor: pointer;
}

.btn-edit{
    background-color: yellow;
}

.btn-delete{
    background-color: red;
}

.btn-view{
    background-color: green;
}

Now we will add working to edit button in the home page. Let's perform update operation on realtime database in this we need a id for updating the particular record. Below is the implementation with the comments

import React, { useState, useEffect } from 'react';
import fireDb from '../firebase';
import { toast } from 'react-toastify';
import { useHistory, useParams } from 'react-router';
import "./Add.css"

const intialstate = {
    name: "",
    genre: "",
    myPersonalRating: ""
}

const Add = () => {
    const [state, setState] = useState(intialstate);
    const [data, setData] =useState({});
    const { name, genre, myPersonalRating } = state;

    const {id} =useParams();
    // STEP -1 FIRST LETS POPULATE THE FORM IF DATA IS AVAILABLE and only if id is also there
    useEffect(() => {
      fireDb.child("Anime").on("value",(snapshot) =>
      {
          if(snapshot.val()!==null)
          {
              setData({...snapshot.val()});
          }
          else 
          {
              setData({});
          }
      });
      // CLEANUP
      return () => {
          setData({});
      };
    },[id]);

    useEffect(() => {
        if(id)
        {
           setState({...data[id]});
        }
        else 
        {
            setState({...intialstate});
        }
        return () =>{
            setState({...intialstate});
        };
    },[id,data]);

    const history = useHistory();

    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setState({ ...state, [name]: value });
    };
    // here is handlesubmit function where an event is passed
    const handleSubmit = (e) => {
        e.preventDefault();
        // validating if any of the fields is emepty than show an error with the use of toastify
        if (!name || !genre || !myPersonalRating) {
            toast.error("All Fields are mandatory")
        }
        else {
            // imp part to push the values in the database with checking the error also if not than display success
            if(!id)
            {
                fireDb.child("Anime").push(state, (err) => {
                    if (err) {
                        toast.error(err);
                    }
                    else {
                        toast.success("Added Successfully")
                    }
                });
            }
            // if already exsists and we want to modify it 
            else 
            {
                fireDb.child(`Anime/${id}`).set(state, (err) =>{
                   if(err){
                       toast.error(err);
                   }
                   else 
                   {
                       toast.success("Updated Successfully")
                   }
                }
                )
            }


            // here we are adding a delay of 3 sec and than redirectig it to home page after adding 
            setTimeout(() => history.push("/"), 300);
        }
    };
   // below is the form implementation of the three input fields which we are asking from the user
    return (
        <div style={{ marginTop: "100px" }}>
            <form style={{ margin: "auto", padding: "15px", maxWidth: "400px", alignContent: "center" ,
            color: "brown"}}
                onSubmit={handleSubmit}> 
                <label htmlFor="name">Anime Name</label>
                <input type="text" id="name"
                    name="name"
                    placeholder="Anime Name"
                    value={name || ""}      // value can be empty or already there
                    onChange={handleInputChange} />

                <label htmlFor="genre">Genre</label>
                <input type="text" id="genre"
                    name="genre"
                    placeholder="Anime genre"
                    value={genre || ""}
                    onChange={handleInputChange} />

                <label htmlFor="MyPersonalRating">MyPersonalRating</label>
                <input type="number" id="myPersonalRating"
                    name="myPersonalRating"
                    placeholder="Rate It"
                    value={myPersonalRating || ""}
                    onChange={handleInputChange} />
                {/* If id is there than upadte otherwise save */}
                <input type="submit" value={id ? "update":"save"}/>  
            </form>
        </div>
    )
}

export default Add

Now the last part adding functionality to our view button In this we will be displaying a particular anime details on a separate page.

import React, { useEffect, useState } from 'react'
import fireDb from '../firebase';
import { Link } from "react-router-dom";
import { useParams } from 'react-router';
import './View.css'
const View = () => {

    const [anime,setAnime] = useState({});
    const {id} = useParams();
    useEffect(() => {
        fireDb.child(`Anime/${id}`).get().then((snapshot) => {
            if(snapshot.exists())
            {
                setAnime({...snapshot.val()});
            }
            else 
            {
                setAnime({});
            }
        });
    },[id]);
    console.log("anime",anime);
    return (
        <div style={{marginTop: "150px"}}>
            <div className="card">
                <div className="card-header">
                    <p>Anime Detail</p>
                    </div>
                    <div className="container">
                        <strong>ID: </strong>
                        <span>{id}</span>
                        <br/>
                        <br/>

                        <strong>Anime_Name: </strong>
                        <span>{anime.name}</span>
                        <br/>
                        <br/>

                        <strong>Anime_Genre: </strong>
                        <span>{anime.genre}</span>
                        <br/>
                        <br/>

                        <strong>My_Personal_Rating: </strong>
                        <span>{anime.myPersonalRating}</span>
                        <br/>
                        <br/>
                      <Link to="/">
                          <button className="btn btn-edit"> Head to Home</button>
                      </Link>
                    </div>
              </div>
              </div>
    )
}

export default View

IT's CSS file

.card{
    width: 30%;
    display: flex;
    flex-direction: column;
    border: red solid;
    align-content: center;
    margin: 0 auto;
}

.card-header {
    height: 30%;
    background: black;
    color: grey;
    text-align: center;
}

.card-header p {
    font-size:20px;
}

.container {
    padding: 4px 16px;
}

Let's have a look at how our web app looks like , apologies for the bad styling in advance.

Image description
Thank you!
Github


This content originally appeared on DEV Community and was authored by Kirti


Print Share Comment Cite Upload Translate Updates
APA

Kirti | Sciencx (2021-12-07T06:18:35+00:00) CRUD operation on Firebase Realtime database. Retrieved from https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/

MLA
" » CRUD operation on Firebase Realtime database." Kirti | Sciencx - Tuesday December 7, 2021, https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/
HARVARD
Kirti | Sciencx Tuesday December 7, 2021 » CRUD operation on Firebase Realtime database., viewed ,<https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/>
VANCOUVER
Kirti | Sciencx - » CRUD operation on Firebase Realtime database. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/
CHICAGO
" » CRUD operation on Firebase Realtime database." Kirti | Sciencx - Accessed . https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/
IEEE
" » CRUD operation on Firebase Realtime database." Kirti | Sciencx [Online]. Available: https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/. [Accessed: ]
rf:citation
» CRUD operation on Firebase Realtime database | Kirti | Sciencx | https://www.scien.cx/2021/12/07/crud-operation-on-firebase-realtime-database/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.