To implement a search bar functionality in an e-commerce website, you typically start by creating a component that includes an input field where users can enter search terms. Here’s a brief description of the approach:
Features:- Component Setup: Create a React component (e.g., ProductList) where you will implement the search bar. This component will fetch and display the list of products.
- State Management: Use React’s useState hook to manage the search term entered by the user. This state will update dynamically as the user types into the search bar.
- Filtering Logic: Incorporate filtering logic to match products based on the search term. You can filter products by their names or any other relevant criteria. Ensure this filtering occurs on the client side to provide instant feedback to the user.
- Integration with Product List: Integrate the search functionality into the product list rendering. Filter the products based on the current search term state and render the filtered results.
- User Interaction: Implement event handlers (onChange for the search input) to update the search term state dynamically as the user types. This allows for real-time filtering of products.
Approach to Implement Search Bar- Managed the nameFilter state using useState to store the search term entered by the user.
- Utilized Array.prototype.filter() to create filteredProducts, which filters the products array based on whether each product’s name property includes the nameFilter.
- Implemented case-insensitive comparison by converting both product.name and nameFilter to lowercase using toLowerCase().
- Implemented an input field (name-filter) where users can type their search terms.
- Linked the value of the input to nameFilter and attached an onChange event handler (handleNameFilterChange) to update nameFilter as the user types.
Example: Implementing Search Bar
CSS
/* Product List Container */
.product-list-container {
padding: 20px;
}
.product-list {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
margin: 20px 0;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.go-to-cart {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
}
/* Product Card */
.product-card {
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: transform 0.3s ease;
width: 200px;
text-align: center;
text-decoration: none;
color: #333;
padding: 15px;
}
.product-card:hover {
transform: translateY(-5px);
}
/* Product Image */
.product-card img {
max-width: 100%;
height: auto;
border-bottom: 1px solid #ddd;
padding: 10px;
box-sizing: border-box;
}
/* Product Name */
.product-card h3 {
font-size: 18px;
margin: 10px 0;
height: 50px;
/* Fixed height for consistency */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Product Price */
.product-card p {
font-size: 16px;
color: #B12704;
margin: 10px 0;
}
/* Add To Cart Button */
.product-card button {
background-color: #ff9900;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 10px 0;
cursor: pointer;
border-radius: 4px;
transition: background-color 0.3s ease;
}
.product-card button:hover {
background-color: #e68a00;
}
.filters input {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
width: 200px;
}
.filters select {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.name-filter {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
width: 300px;
}
JavaScript
//App.js
import React, { useState } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import ProductDetail from "./components/ProductDetail.js";
import AddProduct from "./components/AddProduct.js";
import ProductList from "./components/ProductList.js";
import Cart from "./components/Cart.js";
import CheckoutForm from "./components/CheckoutForm.js";
import Login from "./components/Login";
import SignUp from "./components/SignUp.js";
import UserAccount from "./components/UserAccount.js";
import Home from "./components/Home.js";
const App = () => {
const [cart, setCart] = useState([]);
return (
<Router>
<Routes>
<Route path="/product/:id" element={<ProductDetail />} />
<Route path="/add" element={<AddProduct />} />
<Route
path="/product"
element={<ProductList setCart={setCart} cart={cart} />}
/>
<Route path="/cart" element={<Cart cart={cart} setCart={setCart} />} />
<Route path="/checkout" element={<CheckoutForm />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<SignUp />} />
<Route path="/account" element={<UserAccount />} />
<Route path="/" element={<Home />} />
</Routes>
</Router>
);
};
export default App;
JavaScript
//ProductList.js
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
import "./ProductList.css"; // Import the CSS file
const ProductList = ({ cart, setCart }) => {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [nameFilter, setNameFilter] = useState("");
const [priceRange, setPriceRange] = useState("");
const navigate = useNavigate();
useEffect(() => {
const fetchProducts = async () => {
try {
const { data } = await axios.get("http://localhost:5000/api/products");
setProducts(data);
setLoading(false);
} catch (err) {
setError(err.message);
setLoading(false);
}
};
fetchProducts();
}, []);
const addToCart = (product) => {
setCart((prevCart) => [...prevCart, product]);
};
const goToCart = () => {
navigate("/cart");
};
const handleNameFilterChange = (e) => {
setNameFilter(e.target.value);
};
const handlePriceRangeChange = (e) => {
setPriceRange(e.target.value);
};
const filteredProducts = products.filter((product) => {
const matchesName = product.name
.toLowerCase()
.includes(nameFilter.toLowerCase());
const matchesPrice =
priceRange === "" ||
(priceRange === "0-50" && product.price <= 50) ||
(priceRange === "50-100" && product.price > 50 && product.price <= 100) ||
(priceRange === "100+" && product.price > 100);
return matchesName && matchesPrice;
});
return (
<div className="product-list-container">
<div className="header">
<button className="go-to-cart" onClick={goToCart}>
Go to Cart
</button>
<input
type="text"
placeholder="Search by name"
value={nameFilter}
onChange={handleNameFilterChange}
className="name-filter"
/>
<h2>Product List</h2>
</div>
<div className="filters">
<select onChange={handlePriceRangeChange} value={priceRange}>
<option value="">All Prices</option>
<option value="0-50">0 - 50</option>
<option value="50-100">50 - 100</option>
<option value="100+">100+</option>
</select>
</div>
{loading ? (
<h3>Loading...</h3>
) : error ? (
<h3>{error}</h3>
) : (
<div className="product-list">
{filteredProducts.map((product) => (
<div key={product._id} className="product-card">
<Link to={`/product/${product._id}`}>
<img src={product.imageUrl} alt={product.name} />
<h3>{product.name}</h3>
<p>${product.price}</p>
</Link>
<button onClick={() => addToCart(product)}>Add To Cart</button>
</div>
))}
</div>
)}
</div>
);
};
export default ProductList;
Output
|