Step 1: Create a controller
and route
for search functionality in your backend
//controller
const searchBlog = async (req, res) => {
const searchTerm = req.query.q; // Assuming 'q' as the search parameter
try {
const results = await Blog.find({
$or: [
{ title: { $regex: searchTerm, $options: 'i' } }, // Case-insensitive search for title
{ content: { $regex: searchTerm, $options: 'i' } }, // Case-insensitive search for content
],
});
res.json(results);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
//route
blogRouter.get("/search",blogControllers.searchBlog);
Step 2: As we are using Redux then move into your api
file and make a request
to the above created endpoint
import axios from "axios"
const API = axios.create({baseURL:"http://localhost:8800/"});
export const searchBlogs = (searchTerm) => API.get(`blogs/search?q=${searchTerm}`);
Step 3: Now create an action
for this functionality
import * as api from "../api";
import {
SEARCH_BLOGS
} from "../constants/actionTypes";
export const searchBlogs = (searchTerm) => async (dispatch) => {
try {
const { data } = await api.searchBlogs(searchTerm);
dispatch({ type: SEARCH_BLOGS, payload: data });
} catch (error) {
console.log(error);
}
};
Step 4: Create a reducer
for this action
import { CREATE_BLOG, DELETE_BLOG, FETCH_BLOGS, FETCH_BLOG_ID, SEARCH_BLOGS, UPDATE_BLOG } from "../constants/actionTypes";
export default (blogs = [], action) => {
switch (action.type) {
case SEARCH_BLOGS:
return action.payload;
default:
return blogs;
}
};
Step 5: Move into the component
in which you want to include this search functionality
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getBlogs, searchBlogs } from "../actions/blogs";
import { NavLink } from "react-router-dom";
import Loader from "./Loader"; // Import the Loader component
const Blogs = () => {
const dispatch = useDispatch();
const blogs = useSelector((state) => state.blogs);
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(true); // New state for loading indicator
const handleSearch = () => {
if (searchTerm.trim() !== "") {
dispatch(searchBlogs(searchTerm));
} else {
dispatch(getBlogs());
}
};
return (
<div>
<input
type="text"
placeholder="Search blogs"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<button onClick={handleSearch}>Search</button>
{isLoading ? (
<Loader /> // Display the loader while fetching blogs
) : (
blogs.map((item, index) => {
return (
<div key={index}>
<p>{item.content}</p>
</div>
);
})
)}
</div>
);
};
export default Blogs;
Loader Component
import React from 'react';
import './Loader.css'; // Make sure to create Loader.css file
const Loader = () => {
return (
<div className="loader-container">
<div className="loader"></div>
</div>
);
};
export default Loader;
/* Loader.css */
.loader-container {
display: flex;
justify-content: center;
align-items: center;
/* height: 100vh; */
}
.loader {
border: 4px solid rgba(0, 0, 0, 0.1);
border-top: 4px solid #000;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}