Get started with Rowy in minutes
Firebase is a powerful Backend-as-a-service platform that will give you superpowers as a React developer, but you need to learn a minimum to get started: in the following article, you’ll read how to query data stored in Firebase / Firestore from React in only 10 minutes.
Developing on Firebase can be daunting. There is a lot of documentation to go through, and the database interface isn’t particularly user-friendly. At Rowy, we provide a content management system on top of Google Firestore to help front-end developers use it without the hassles. To save ourselves an hour of configuration work, and many more hours down the road, we are going to use Rowy as a Firebase CMS for a React app.
First, follow the installation guide or use the Deploy shortcut to let Rowy guide you. It takes 5 minutes to get started:
We name the project React Firestore Query
. Rowy will take care of setting up Firestore, Firebase’s database management system.
You are ready to use Firestore with React as soon as your project is created:
We now create a database from scratch for our test app.
First, create a new table from a ready-to-use template. Click “Show all templates” on your Rowy project’s homepage and pick “Countries”:
Rowy takes care of setting up a Firestore collection called countries
and populate it with properties
:
The database is empty. We just need to import some data by using the Countries demo’s import button. Download the data from the demo as a CSV file:
And then simply re-import it in your own countries
table:
That’s it! We now have a database that contains 244 data points, and it only took a minute!
A NoSQL database like Firestore is a set of collections (called tables in Rowy) containing documents. In this example, our collection is a country list, and this collection contains 244 countries as single documents.
Now that our test dataset is ready, we need to obtain the accesses to Firestore’s API to use in our front-end.
Head to your project’s Firebase Console and navigate to “Project settings”. In the first tab, you’ll find the following code that contains your Firebase configuration:
Before you head to VSCode, go to the side panel. Click Build → Firestore database and navigate to the Rules tab. During development, we need to disable authentication to avoid running into permission issues.
Add the following security rule:
match match /{document=**} {
allow read, write: if true;
}
You will obtain something like this:
User authentication is outside the scope of this article, but know that you’ll need some way to recognize your users to run an app in production. For now, keep your Firebase configuration a secret until the development phase is over.
Create a new React app:
npx create-react-app react-firestore-query
We won’t need much code to get started, so go ahead and empty your App
function:
src/App.js
function App() {
return (
<div className="App">
</div>
)
}
export default App
Use the Firebase config you obtained in step 3 to connect to your Firestore database:
src/services/db.mjs
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
let db = false;
export const getDb = () => {
if(!db){
const firebaseConfig = {
apiKey: <API_KEY>,
authDomain: <AUTH_DOMAIN>,
projectId: <PROJECT_ID>,
storageBucket: <STORAGE_BUCKET>,
messagingSenderId: <MESSAGING_SENDER_ID>,
appId: <APP_ID>
}
const app = initializeApp(firebaseConfig)
db = getFirestore(app)
}
return db
}
This code implements a singleton pattern that requests a Firestore database connection to perform queries. This way, we avoid reconnecting each time we send a request. It’s nice to avoid saturating the back-end server and decrease the Firestore bill.
Our countries
collection already contains 244 documents, as you can see in Rowy, so we can go ahead and get them from Firestore to display them in React.
To keep the code modular, let’s create a standalone service to manage our API calls to Firebase:
src/services/countries.mjs
import { getDocs, collection } from "firebase/firestore";
import { getDb } from "./db.mjs"
const collection_name = "countries"
export const findAll = async () => {
const doc_refs = await getDocs(collection(getDb(), collection_name))
const res = []
doc_refs.forEach(country => {
res.push({
id: country.id,
...country.data()
})
})
return res
}
The findAll function will fetch all the documents within the countries
collection and return them as an array of countries, ready to be consumed by our React app.
Let’s create a CountryList
component that will display all the countries:
src/App.js
import CountryList from './components/country-list.js'
function App() {
return (
<div className="App">
<CountryList/>
</div>
)
}
export default App
The CountryList
component encapsulates all the back-end logic, handles state changes, and displays the content:
src/components/country-list.js
import { useState, useEffect } from 'react'
import { findAll } from '../services/countries.mjs'
import CountryListItem from './country-list-item.js'
function CountryList() {
const [loading, setLoading] = useState(false)
const [countries, setCountries] = useState([])
const fetchData = async () => {
setLoading(true)
const res = await findAll()
setCountries([...res])
setLoading(false)
}
useEffect(() => {
fetchData()
}, [])
return (
<section>
<header>
<h2>Countries</h2>
</header>
{ loading &&
<p>loading...</p>
}
<ul>
{countries.length > 0 && countries.map(country => (
<CountryListItem country={country}/>
))}
</ul>
</section>
)
}
export default CountryList
src/components/country-list-item.js
function CountryListItem(props) {
const { country } = props
return (
<li key={country.id}>
<h3>{country.flag} {country.name} ({country.code})</h3>
<p>Capital: {country.capital}</p>
<p>Continent: {country.continent}</p>
</li>
)
}
export default CountryListItem
That’s it! Just yarn start
the React app and you’ll see your countries data stored in Rowy:
Similarly, you can also query Firestore to get a single document by id:
src/services/countries.mjs
import { doc, getDoc } from "firebase/firestore";
import { getDb } from "./db.mjs"
const collection_name = "countries"
export const findOne = async id => {
const d = await getDoc(doc(getDb(), collection_name, id))
return d.data()
}
We managed to request documents from Firestore, but what about more complex queries? That’s where the query
function comes in. The following code is equivalent to retrieving the whole collection:
src/services/countries.mjs
const doc_refs = await getDocs(query(collection(getDb(), collection_name)))
Which gives us the exact same result:
The only difference is the use of the function query
, which is redundant here. The thing is query
can take additional parameters to perform fine-grained requests, as we will now see.
The where
clause allows us to filter data according to one or more properties:
src/services/countries.mjs
export const findByContinent = async () => {
const collection_ref = collection(getDb(), collection_name)
const q = query(collection_ref, where("continent", "==", "Asia"))
const doc_refs = await getDocs(q);
const res = []
doc_refs.forEach(country => {
res.push({
id: country.id,
...country.data()
})
})
return res
}
In this example, we obtain the list of countries based in Asia:
We can also use the query
function to sort our results with the orderby
clause and limit their number with the limit
clause. For example, let’s sort countries by alphabetical order and get the first 5 results:
src/services/countries.mjs
export const findByAlphabeticalOrder = async () => {
const collection_ref = collection(getDb(), collection_name)
const q = query(collection_ref, orderBy("name"), limit(5))
const doc_refs = await getDocs(q);
const res = []
doc_refs.forEach(country => {
res.push({
id: country.id,
...country.data()
})
})
return res
}
Which returns the follow result:
Firestore doesn't provide full-text search out-of-the-box, but you can easily integrate a search service like Meilisearch to do just that.
Check out our article on how to integrate Meilisearch with Rowy to learn more. It will walk you through the whole process in as little as 5 minutes:
It all works right away and you won't need to manage a single search index or write a single line of code thanks to Rowy's support.
And this is how you perform basic queries with Firestore in React, folks!
If you haven’t subscribed to Rowy already, we’ve got plenty of templates to get you up and running in 2 minutes! So don’t hesitate and try Rowy for free. It will save you hours of back-end development time as your React code base evolves.