Integrating React-Select and Firebase firestore for text-searching

Clipversity
4 min readMar 7, 2020

In this article, we will implement the in-text-searching operation in Firebase firestore and search the data by using React-Select.

Full-text-searching in Firebase

according to Firebase official document:

Cloud Firestore doesn’t support native indexing or search for text fields in documents. Additionally, downloading an entire collection to search for fields client-side isn’t practical.

Firebase suggest developer use Algolia (a third-party search service) for implementing Full-text-searching. I do used Algolia for my project, however Community Plan of Algolia contains a request limit, for those who need to search a Tag or Label, using “.where” operation in Firebase firestore will much suitable.

About React-Select and Firebase firestore integration

React-Select is a package allowing people to do the async select control in the React App. In this article, we will cover how to implement a Tag search or a Label search by only using Firebase firestore. If the user cannot found their tag or label, they can create a new one and upload to firestore.

1- Get Started

Once you create a new firebase project (or use the existing one), create a new Collection called “Tag” and create a new document as follow:

be aware that the filed “plainName” should not contain any symbols, space and all lowercase letter

be aware that the filed “plainName” should not contain any symbols, space and all lowercase letter

plainName will be used to do a string search, while there are no limitation of the filed tagName .

Create our React App

$ npx create-react-app myapp

we also need to install firebase and react-select package

$ npm install firebase$ npm install react-select

Connect our React App to firebase

To link firebase into our React App, we need to get our config from the firebase console

Project Settings > General > Your Apps (you may required to create a web app first)

We first create firebase.js and place it in our project directory

add the following code in firebase.js

firebase.js

import * as firebase from 'firebase';


const firebaseConfig = {
apiKey: <YOUR-API-KEY>,
authDomain: <YOUR-AUTH-DOMAIN>,
databaseURL: <YOUR-DATABASE-URL>,
projectId: <YOUR-PROJECTID>,
storageBucket: <YOUR-STORAGE-BUCKET>,
messagingSenderId: <YOUR-MESSAGING-SNEDER-ID>,
appId: <YOUR-APP-ID>
};
firebase.initializeApp(firebaseConfig)

firebase.firestore();

export default firebase;

Then, we clear up our App.js

App.js

import React, {Component} from 'react'
import
firebase from './firebase'
const db = firebase.firestore();class App extends Component{
constructor(props) {
super(props);
this.state={
selectedTag: []
}
}

render() {
return (
<div>

</div>
);
}

}
export default App

in the code, the variable “db” is a client for doing any firestore operation. The state selectedTag store the tag which is selected.

2- Import AsyncSelect from React-Select in our app

in App.js, import the following package:

import AsyncSelect from 'react-select/async';

add the following code within the <div> in App.js

<div>
<AsyncSelect
loadOptions={this.loadOptions}
onChange={this.handleOnChange}
/>
<p>Selected Tag:</p>
{
this.state.selectedTag.map(e => {
return (
<li key={e.value}>
{e.label}
</li>
)
})
}
</div>

In AsyncSelect, it is required two function, including loadOptions ( send the request to firebase for the matching tags) and onInputChange (when user select an object)

then we create these two function (put it inside class App):

loadOptions = async (inputValue) => {
inputValue = inputValue.toLowerCase().replace(/\W/g, "");
return new Promise((resolve => {
db.collection('Tag')
.orderBy('plainName')
.startAt(inputValue)
.endAt(inputValue + "\uf8ff")
.get()
.then(docs => {
if (!docs.empty) {
let recommendedTags = []
docs.forEach(function (doc) {
const tag = {
value: doc.id,
label: doc.data().tagName
}
recommendedTags.push(tag)
});
return resolve(recommendedTags)
} else {
return resolve([])
}
})

})
)
}

Any input will call function loadOptions()

Let’s understand the full process:

1- In this function we first remove all the symbols, spaces and lower case the input string.

2- we request the data from firebase, where the field “plainName” with the starting letter as input string and last letter “\uf8ff”

The \uf8ff character used in the query above is a very high code point in the Unicode range. Because it is after most regular characters in Unicode, the query matches all values that start with a b.

3- once firebase return a docs result, if there is not empty, we get the document id by doc.id and the value of field tagName by doc.data().tagName

Be noted that react-select only accept option data modal as:

an array with an object / objects included value field and label field

[
{
value: "MY-VALUE",
label : "MY-LABEL"
}
]

Last but not least, our handleOnChange function:

handleOnChange = (tags) => {
this.setState({
selectedTag: [tags]
})
}

3- Let’s try it

When you try “j” , the result will display.

When you select the option, your selected object will be displayed

Done!

You can download the full App.js source code through here.

--

--