A ReactJS Search Bar Powered By Firebase: A Step-by-Step Guide (2023)

A search bar is always useful in an app to help users quickly find the content or feature they are looking for without having to navigate through multiple screens or menus. It also provides a quick way to perform specific actions, making the user interface more convenient and friendly to use.

Building a search bar is not a difficult task, but it can be time-consuming if you don't know where to start. In this tutorial, we will build a ReactJS search bar using Firestore.

1. React Component

In your React project, create a new SearchBar.js component and copy / paste the following code. We use Tailwind CSS for quick styling:

import React, { useState } from 'react';

const SearchBar = () => {

    const [query, setQuery] = useState("")

    function search(e){
        e.preventDefault()
        setQuery(e.target.value)

        ...
    }

    return (
        <div className="w-full max-w-xl flex mx-auto p-20 text-xl">
            <input
                type="text"
                className="w-full placeholder-gray-400 text-gray-900 p-4"
                placeholder="Search"
                onChange={search}
                value={query}
            />
            <button className="bg-white p-4">🔍</button>
        </div>
    );
};

export default SearchBar;

The component uses the useState hook to define a state variable query which is initialized to an empty string "". The setQuery function is used to update the value of query as needed.

The search function is defined within the component, which takes an event object e as its argument. This function is triggered when the user types in the search bar and presses the enter key or submits the form. preventDefault() method is used to prevent the default behavior of the browser when the form is submitted. The current value of the search bar input field is obtained using e.target.value and is stored in the query state variable by calling setQuery() function.

The result is as follow:

Picture of the search bar as a React component - 0.webp

2. Basic Search Query

Let's take Rowy's Countries demo as a database example. The search bar will allow users to search for countries:

Picture of a database of countries from a Rowy demo - 1.webp

Rowy is a Firebase CMS that makes it easy to manage databases in a familiar spreadsheet user interface. You can directly use Firebase's API to query data in your React app.

One simple way to search for data is to use a Firestore query with a where clause to filter documents according to our search query. For example, if we want to search for countries that start with the letter "A", we can use the following query:

const query = db.collection("countries").where("name", ">=", "A").where("name", "<=", "A\uf8ff")

Similarly, we can search countries by continent, country code, capital, and so on.

In our React component, all we have to do is to replace the ... in the search function with the appropriate Firestore code:

import { getFirestore, getDocs, collection, where, query } from "firebase/firestore"; 
import { initializeApp } from "firebase/app";

const [results, setResults] = useState([])

function search(e){
    e.preventDefault()
    setQuery(e.target.value)

    const firebaseConfig = {...}

    const app = initializeApp(firebaseConfig)

    db = getFirestore(app)

    const collection_ref = collection(, 'countries')
    const q = query(collection_ref, where("name", ">=", "A"), where("name", "<=", "A\uf8ff"))
    const doc_refs = await getDocs(q)

    const res = []

    doc_refs.forEach(country => {
        res.push({
            id: country.id, 
            ...country.data()
        })
    })

    setResults(res)
}

When the search function is called, it initializes a Firebase app using the firebaseConfig object containing configuration details you can find in your Firebase Console. The getFirestore function then initializes the Firestore database to access it.

The collection function creates a reference to the countries table in Rowy, then we retrieve the countries that start with the letter 'A'.

You can then use the results state variable in the React component to render the search results however you see fit.

There is one problem with this method though: Firebase queries are limited in terms of flexibility. A single error in the query can impact the search results. For example, searching for "frnace" will return no results because the query doesn't match exactly the stored document's name: "france". For this reason, full-text search is often preferred to improve user experience.

3. Advanced Full-Text Search

Full-text search is a feature to search for documents containing a specific word or phrase, with more degrees of flexibility compared to basic match queries.

Even though Firestore doesn't provide full-text search out-of-the-box, you can easily integrate a search service like Meilisearch in Rowy.

Picture of MeiliSearch's landing page - 2.webp

The installation process is simple:

  1. Create a new project on Meilisearch for free.
  2. Add your search instance URL and API key in your Rowy project's settings under the Services tab.
  3. Enable the tables you want to index in Meilisearch.

Meilisearch automatically indexes your data in the background and you won't need to update it every time a change occurs―it's all automated!

In your React app, you can just query Meilisearch using the instance URL and API key you added in Rowy's settings:

const results = await fetch(`${MEILISEARCH_INSTANCE_URL}/indexes/countries/search`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${MEILISEARCH_MASTER_KEY}`
    }, 
    body: JSON.stringify({
        q: 'spain'
    })
}).then(res => res.hits)

Your search bar is now fully functional! One last suggestion: when implementing real-time search, you can add a debounce function to the search function to avoid sending too many requests to either Firebase or Meilisearch:

import { debounce } from 'throttle-debounce'

const debounceSearch = debounce(500, search)

Debouncing guarantees that a function is only executed once in a series of calls. Without it, the search function would be called every time the user types a letter, which would result in a lot of unnecessary requests.

Join Us On Discord

In this tutorial, we learned how to implement a search bar in React using Firebase queries and Meilisearch's full-text search. We also saw how to add a debounce function to avoid sending too many requests.

If you liked this article, you'll probably enjoy our Discord community as well. We help each other make things with less code, and we're always happy to welcome new members!

Get started with Rowy in minutes

Continue reading

Browse all