PJ’s Pooch Attires — An app built with React

Jeni Dang
5 min readJan 25, 2022
PJ’s Pooch Attires Homepage with sliders that showcase store ‘all time favorite products” for customers to enjoy.
Image #1: PJ’s Pooch Attires Homepage with sliders that showcase store ‘all time favorite products” for customers to enjoy.
Image #2: Products page displaying all the store products with search and filter feature
Image #3 left: Items inside cart ready to checkout — — Image #4 right: Cart is empty after customer checkout
Image #5: New customer can create an account to track their order status

PJ’s Pooch Attires is an application that was inspired by my dog, PJ and my grandparents that love to do online window shopping ever since they learned how to surf the internet with their tablet/iPad.

The goal of this project was to create an app that is simple to use, especially easy on the user’s eyes with the display and easy to navigate. For the UI of this app, I tried to use a different UI for every component, but keeping it as similar as possible so the user does not notice the difference.

  • CSS — Cascading Style Sheets
import './css/Details.css'
  • Bootstrap & React BootstrapQuickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.
// with npm
npm install react-bootstrap bootstrap@5.1.3
  • MUI — provides a robust, customizable, and accessible library of foundational and advanced components, enabling you to building your own design system and develop React application faster.
// with npm
npm install @mui/material @emotion/react @emotion/styled
// use styled-components
npm install @mui/material @mui/styled-engine-sc styled-components
  • Semantic UI — User Interface is the language of the web

One of the challenges that I encountered while building this application turns out to be one of my favorites would be implementing the search and filter for the products.

The search feature can search when the product page load to search through the list of products or search the product after the product is filtered.

To achieve this, I declare a new state variable called “search” which will represent our current state and a “setSearch” which will be a function that updates search. I also declare another new state variable called “searchResult” and a “setSearchResult” function. Inside the Product Container, I created a searchHandler function and pass it to the Search component.

...partial code from ProductContainer...const [search, setSearch] = useState('')
const [searchResult, setSearchResult] = useState([])
const searchHandler = (search) => {
setSearch(search)
if (search !== '') {
const newProduct = searchResult.filter((product) => {
return Object.values(product)
.join(' ')
.toLowerCase()
.includes(search.toLowerCase())
})
setSearchResult(newProduct)
} else {
setSearchResult(products)
}
}
return (
<>
<Container>
<Search products={products} term={search} searchKeyword=
{searchHandler}
/>
<ProductList products={searchResult} />
</Container>
</>
Notes: 1) Object.values(product) - will get the object values
2) .join(‘ ‘) - will make a join on the values
3) .toLowerCase() - will make all the values into lowercase
4) .includes(search.toLowerCase() - will check if the values includes in the products or not, and if yes, return true

In the Search Component, I use the useRef hook for the search input.

What is useRef? useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

Example of useRef when a user type in values in the search input: console.log(inputEl.current.value) in the Google Chrome console
import React, { useRef } from "react";function Search({ term, searchKeyword }) {
const inputEl = useRef("")
const getSearchTerm = () => {
//if you console.log(inputEl.current.value) to test in the console, you'll see that it will print every input a user enter in the search area
searchKeyword(inputEl.current.value)
}
return (
<form className="d-flex w-50 mt-2">
<input
className="form-control me-2"
aria-label="Search"
type="search"
ref={inputEl}
value={term}
placeholder="Product Search"
onChange={getSearchTerm}
/>
<button className="btn btn-outline-dark"
type="submit">Search</button>
</form>
);
}
export default Search;

For the filter by product category, I updated the Product Container with a filterResult function and added setSearchResult in the try fetch.


const ProductContainer = () => {
const [loading, setLoading] = useState(true);
const [products, setProducts] = useState([]);
const [search, setSearch] = useState('');
const [searchResult, setSearchResult] = useState([]);
const fetchProducts = async () => {
setLoading(true);
try {
const response = await fetch('http://localhost:3001/products');
const data = await response.json();
setLoading(false);
setProducts(data);
setSearchResult(data);
} catch (error) {
setLoading(false);
alert(error);
}
};
useEffect(() => {
fetchProducts();
}, []);
if (loading) {
return <div>
<Loading />
</div>;
}
const filterResult = (categoryItem) => {
if (categoryItem === 'All') {
setSearchResult(products);
return;
}
const result = products.filter((currentData) => {
return currentData.category === categoryItem;
});
setSearchResult(result);
};
const searchHandler = (search) => {
setSearch(search)
if (search !== '') {
const newProduct = searchResult.filter((product) => {
return Object.values(product)
.join(' ').toLowerCase().includes(search.toLowerCase());
});
setSearchResult(newProduct)
} else {
setSearchResult(products)
}
};
return (
<>
<Container >
<Search products={products} term={search} searchKeyword=
{searchHandler}
/>
<FilterCategory filterResult={filterResult} /
<ProductList products={searchResult} />
</Container>
</>
);
};
export default ProductContainer;

The image below shows the final result for the search and filter by category. User and click on the button to filter or simply type in letter(s) to search for the product.

Example of user search and filter by category on the app

Through this project, I learned to challenge myself to go beyond the lessons and materials that were given. It was tough at first, but as I tried and tried, delete, rewrite, delete, rewrite, I learned there will always be a solution to a problem.

--

--