In this chapter, we're going to learn how to read and write data from Firestore. We're going to build the first bits of our application: the ability to add, update, and remove songs from our chart.
Let's replace content of src/App.js
with a simple HTML form:
import firebase from "firebase/app";
import React from "react";
import "./App.css";
export default function App() {
return (
<div className="App">
<h1>My Favourite Tame Impala Songs</h1>
<h2>Add new song:</h2>
<form name="song" onSubmit={handleSubmit}>
<p>
<label>
Title: <input name="title" required />
</label>
</p>
<p>
<label>
Rating:{" "}
<input name="rating" type="number" min="0" max="100" required />
</label>
</p>
<p>
<button type="submit">Add to chart!</button>
</p>
</form>
</div>
);
}
async function handleSubmit(e) {
e.preventDefault();
const form = e.target;
// 1. Get data from the form
const title = form.title.value;
const rating = parseInt(form.rating.value);
// 2. Get Firestore instance
const firestore = firebase.firestore();
// 3. Add a document to the songs collection with random id
const song = await firestore.collection("songs").add({ title, rating });
alert(`Added ${title} song with id ${song.id}`);
form.reset();
}
In the handleSubmit
handler, we've used Firestore to add entered data as a document to the songs
collection:
const firestore = firebase.firestore();
const song = await firestore
.collection("songs")
.add({ title, rating });
If we'll open our app in a browser, enter some data and submit the form:
And then open the database explorer on Firebase, you'll see that the document has been added successfully:
Now, let's display our list. We'll read all documents from the songs
collection and display as a list using React Hooks. Update src/App.js
:
export default function App() {
// 1. Create a state to store the songs
const [songs, setSongs] = useState();
useEffect(() => {
// 2. Query all documents in the songs collection
firebase
.firestore()
.collection("songs")
.get()
// 3. When the query is resolved, save the documents
// to the state
.then(songs => setSongs(songs.docs));
}, []);
// The rest of the component...
}
We've fetched songs from the database, but when you add a new song, you have to refresh the page to see it. Let's use the Firestore real-time feature and listen to the documents instead of fetching them only when the page loads. Add this code the start of our App
component in src/App.js
:
export default function App() {
const [songs, setSongs] = useState();
useEffect(() => {
return (
firebase
.firestore()
.collection("songs")
// Pass callback to receive updated songs
.onSnapshot(songs => setSongs(songs.docs))
);
}, []);
// The rest of the component...
}
Now let's see how to update documents. We're going to add onChange
callback where we will update the document:
<ul>
{songs
? songs.map(song => (
<li key={song.id}>
{song.data().title}{" "}
<input
value={song.data().rating}
onChange={e => {
// Update the rating:
song.ref.update({ rating: parseInt(e.target.value) });
}}
type="number"
min="0"
max="100"
required
/>
</li>
))
: "Loading..."}
</ul>
You might see that the data saved to the database:
Finally, let's add the ability to remove songs. Update our App
component in src/App.js
:
<button
onClick={e => {
e.preventDefault();
// 1. Confirm the deletion
const confirmDelete = confirm(`Do you want to remove ${data.input}?`);
// 2. Remove the component (the delete function returns a promise)
confirmDelete && song.ref.delete();
}}
>
Remove
</button>
In this chapter you've learned how perform basic operations on Firestore. In the next chapters you'll learn how to authenticate users, how to write query and secure the database.