Read, Write, and Delete Data from the Realtime Database
Learn to read and write data to the Realtime Database and discover different ways to perform read and write operations.
To carry out any operation on the Realtime Database, we must create a reference to the specific path within our database. To do this, we use the ref
function, imported from the firebase/database
subpackage. This function returns a reference to the location in the database that corresponds to the provided path.
The ref
function takes the database instance as its first argument. It can also optionally take the path that the returned reference points to, as its second argument. However, if no path is provided, the function returns a reference to the root of the database:
import { getDatabase, ref } from "firebase/database";// initialise databaseconst db = getDatabase();// reference to database rootconst dbRef = ref(db);// reference to the users/tasks/* pathconst tasksRef = ref(db, "users/tasks/" + user.uid);
Basic write operations
We use the set
function to write data to the database. It overwrites all existing data at the specified location, including all the child nodes, and replaces them with the new values. It takes a reference to the location as its first argument and the values to be written as its second argument:
import { getDatabase, ref, set } from "firebase/database";// initialise databaseconst db = getDatabase();const tasksRef = ref(db, "tasks");const addNewTask = (task, difficulty) => {set(tasksRef, {tasks: task,difficulty,})}
Alternatively, we use the push
function to write new data to the same database location without overwriting the existing data. This function generates a new child node every time data is written to the location and assigns it a unique key:
import { getDatabase, ref, push } from "firebase/database";// initialise databaseconst db = getDatabase();const tasksRef = ref(db, "tasks");const addNewTask = (task, difficulty) => {push(tasksRef, {tasks: task,difficulty,})}
Basic read operations
To read data once from our database, we can use the get
function. This function returns a promise that resolves to give us a snapshot of the queried database location. If we use the get
function excessively, we might encounter performance loss and increased bandwith usage. Because of this, Firebase recommends using a real-time observer to read data:
import { getDatabase, ref, get } from "firebase/database";// initialise databaseconst db = getDatabase();const tasksRef = ref(db, "tasks");get(tasksRef).then((snapshot) => {const data = snapshot.val();console.log(data);}).catch((err) => {console.error(err);});
Listen for changes with an observer
Sometimes when reading data on our application, we may need to observe real-time changes to our database. To listen for changes in a particular location on our database, we can use the onValue
function. This function is triggers by the initial data read. It is also triggered again whenever the data, including its children, changes.
The onValue
function takes a reference to the location to be queried as its first argument. Then, it takes a callback that triggers when the event occurs. We pass a snapshot to this callback. This snapshot contains the data in the queried location. The val()
method on the snapshot returns null
if there is no data at that location:
import { getDatabase, ref, onValue } from "firebase/database";// initialise databaseconst db = getDatabase();const tasksRef = ref(db, "tasks");onValue(tasksRef, (snapshot) => {const data = snapshot.val();console.log(data);});
Delete data from the database
The most direct way to delete data from a database is by calling the remove
function. The function is called on the reference to the location that contains the data.
We can also delete data by specifying null
as the value to be written when calling the set
function on the location:
import { getDatabase, ref, remove } from "firebase/database";// initialise databaseconst db = getDatabase();const tasksRef = ref(db, "tasks");remove(tasksRef).then(() => {console.log("location removed");});
Practice exercise
Study the highlighted lines in the widget below to learn how to read, write, and delete data from the Realtime Database.
import React, { useState } from "react"; import { addNewTask } from "../helpers/database"; function AddTask() { const [input, setInput] = useState({ task: "", difficulty: "easy" }); const handleChange = (e) => { setInput((prevState) => ({ ...prevState, [e.target.name]: e.target.value, })); }; const handleSubmit = (e) => { e.preventDefault(); let { task, difficulty } = input; addNewTask(task, difficulty, setInput); }; return ( <div className="task-form"> <div className="form-input"> <form onSubmit={handleSubmit}> <input name="task" placeholder="Input task" type="text" onChange={handleChange} value={input.task} required /> <label htmlFor="task" className="label-name"> <span className="content-name">Task</span> </label> <br /> <select name="difficulty" id="difficulty" onChange={handleChange} value={input.difficulty} required > <option value="easy">Easy</option> <option value="medium">Medium</option> <option value="hard">Hard</option> </select> <label htmlFor="difficulty" className="label-name"> <span className="content-name">Difficulty</span> </label> <div className="btn"> <button title="submit" aria-label="submit" type="submit"> Submit </button> </div> </form> </div> </div> ); } export default AddTask;
Steps to perform
- Open a new tab and run the widget above. Also open the browser console to view the output of the
onValue
function. - Create new tasks and submit them.
- Notice the new tasks added to the browser console in real time.
- Modify the code for write operations. Use the
set
function to write to the database.