Having a functional search integration will enhance the user interaction on your website. Let’s learn how to add a standard full-text search to your React web app.
Search integration enables you to find things easily on a web application. With search integration, you can look for an item/product without going through the stress of scrolling manually to find the specific item or product.
Search integration means the process of implementing a user search input on a web application to help query the searched value from a connected database.
Having a functional search integration will enhance the user interaction on your website. It will give users a better experience when navigating your web application.
This article includes a step-by-step guide to implementing search integration into a web application.
In this article, you will learn:
To understand this tutorial, you will need to have:
There are two significant types of text search:
The most reliable text search is the full-text search. This search type gives you a better experience when looking for a product/item on a web application. This is the type we’ll focus on today.
Before diving into the code aspect of the post, there are some additional terms you need to know for performing a full-text search:
Let’s begin by setting up our project environment. First, create a project directory.
mkdir siApp
Next, initialize Yarn in the project directory.
yarn init
You will be asked some questions, and then it will automatically generate a package.json file that will contain the responses to the questions you answered earlier. See the basic structure below.
{
"name": "your-app-name",
"version": "1.0.0",
"main": "index.js",
"author": "sproff",
"license": "MIT",
},
Note: If you don’t answer the required questions, it will automatically select a default response for you.
Now you can start installing your packages. But for this tutorial, I will be installing Express.js.
yarn add express
The package will be added to the dependencies inside your package.json file. See the structure below.
{
"name": "your-app-name",
"version": "1.0.0",
"main": "index.js",
"author": "sproff",
"license": "MIT",
"dependencies": {
"express": "^4.17.1",
},
As you can see, the Express package is now a dependency. Now, let’s create a Hello World app inside the index.js
file.
const express = require("express")
const app = express()
const port = 9000
app.get("/", (req, res) => {
res.send("Hello World!")
})
app.listen(port, () => {
console.log(`Server is running on PORT:${port}`)
})
After setting up your index.js file, run node index.js
in your terminal. Then, go to your browser and visit localhost:9000
. You should see your message—“Hello World.”
Next, we need to set up the search controller inside your Node.js application. Create a folder inside your parent folder called controllers
, then create a file inside called product.controller.js
.
// product.controller.js
const searchProduct = async (req, res, next) => {
try {
const { q } = req.query;
const products = await Product.find({ name: { $regex: q, $options: 'i' } });
if (products.length < 1) throw new ErrorHandler(404, 'No product found');
res.status(201).json({
status: 'success',
message: 'Product has been found successfully',
products,
});
} catch (error) {
next(error);
}
};
Note: To set up a controller, you should have created a schema and other basic setups to enable your app to work.
In the code above, we started by declaring a try-catch statement and then assigned query params. Then we declared a variable that will contain a Mongoose attribute of find.
The find attribute tends to query the database whenever you input a particular letter/word. Then you validate your response by checking if the product is available or not by creating a conditional statement.
Next, we need to create a new React app with react-router-dom.
yarn create react-app my-app react-router-dom
Now, we need to set up the route. To set up your route, create a folder called routes and then create a file inside the folder called route.js.
// route.js
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
export const Routes = () => {
return (
<Router>
<Switch>
<Route path="/search">
<SearchResults />
</Route>
<Route exact path="/">
<Home />
</Route>
</Switch>
</Router>
);
};
The code above contains the route that will handle the transition of your pages.
Next, we need to create a new file for search input. Navigate to your parent folder, create a subfolder called component, and then create the search input file using this command below.
touch SearchInput.jsx
Paste the following code into SearchInput.jsx
.
// SearchInput.jsx
import React, { useState} from "react";
import { useHistory } from "react-router-dom";
export const SearchInput = () =>
{
const [search, setSearch] = useState("");
const history = useHistory();
return (
<div>
<InputGroup>
<Input
onChange={(e) => {
setSearch(e.target.value)
}}
type="search"
placeholder="Search product"
/>
<InputRightElement>
<div>
<button onClick={() => history.push(`/search?query=${search}`)} >Search</button>
</div>
</InputRightElement>
</InputGroup>
</div>
)
}
A state is created in the code above to listen to your input; the setSearch
handles the onChange
event; and the search
state handles the input rendering, which will be triggered when you click the search button.
The useHistory
hook provides access to the history instance, which is used to navigate. The action executed inside the button
tag means that you are listening for an onClick
event that will trigger the history.push
.
This will push you to another route (/search) created earlier, then store your input inside the search
state.
The search
state will be passed as a query to the new route (/search) and then render the output based on the database results.
Next, create a new file for search results. Navigate to your parent folder, create a subfolder called pages
, and then create the search input file using this command below.
touch SearchResults.jsx
Paste the following code into SearchResults.jsx
.
// SearchResults.jsx
import React, { useEffect, useState } from "react";
import { Link, useLocation, useParams } from "react-router-dom";
export const SearchResults = () => {
const [searchResults, setSearchResults] = useState([]);
const [error, setError] = useState(false);
const location = useLocation();
const query = new URLSearchParams(location.search).get("query");
const { slug } = useParams();
useEffect(() => {
const searchProduct = async () => {
try {
const { data } = await axios.get(`API_URL/search?q=${query}`); setSearchResults(data.products);
} catch (error) {
setError(error.response?.data?.message);
}
};
searchProduct();
}, []);
return (
<div>
{searchResults.map((searchResult) => (
<div
key={searchResult.id}
<p>{searchResult.name}</p>
</div>
))}
</div>
)
}
Above, we created two React hooks which are the useState
and the useEffect
. Two different states have been created, which are the searchResults
and error
states.
The useState hook declares state variables to preserve some values between the function calls, and it returns a pair of values: the current state and a function that updates it. The useEffect
hook helps in
data fetching, while the searchResults
state handles the data coming from a specific API. Lastly, the error state handles errors coming from the overall actions.
The useLocation
hook returns the location object representing the current URL. It serves as a redirect to another page whenever you click on a component. The hook is then attached to the query variable where an event will
trigger it.
The API URL is attached to a search query that will enable the stored user input to trigger the .find
attribute in Mongoose, which was declared earlier. The setSearchResults
state will listen
to the results obtained from the API and then render it to the user using a map function by mapping through with the searchResults state.
Finally, we have created a functional search input with standard search results without any external library needed. We touched on the different types of text search, discussed what react-router-dom is, and highlighted a standard way to perform a full-text search.
Chinedu is a tech enthusiast focused on full-stack JavaScript and Infrastructure engineering.