Integrating React-Select and Firebase firestore for text-searching
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
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
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.