I have created a simple search item page where
- On load, users will see all the items under their categories.
- Users will be able to search items.
- If found, items will be displayed or otherwise "No Items" will get displayed.
However, I still believe the code below is not optimized and can be shortened as I can see reluctant codes for every category mapping.
I’d appreciate to know how should I use one Filter and One mapping for the SECTION TO OPTIMIZE
below. Thanks.
Code : https://codesandbox.io/s/beautiful-brahmagupta-79i9ih?file=/src/App.js
import React, { useEffect, useState } from "react";
import "./index.css";
const object = [
{ category: "One", name: "Mishanta" },
{ category: "One", name: "Virichia" },
{ category: "Two", name: "Steven" },
{ category: "Two", name: "Vikhostana" },
{ category: "Three", name: "Rockhosita" },
{ category: "Three", name: "Johnsonow" },
{ category: "Three", name: "Urvesta" },
{ category: "Two", name: "Dipuota" },
{ category: "One", name: "Dikhosta" }
];
const App = () => {
const [searchedInput, setSearchedInput] = useState("");
const [searchedItem, setSearchedItem] = useState([]);
const [items, setItems] = useState([]);
useEffect(() => {
setItems(object);
}, []);
useEffect(() => {
if (searchedInput !== "") {
const arr = JSON.parse(JSON.stringify(object));
const filteredData = arr.filter((value) => {
const searchStr = searchedInput.replace(/s/g, "").toLowerCase();
const nameMatches = value.name.toLowerCase().includes(searchStr);
return nameMatches;
});
setSearchedItem(filteredData);
}
}, [searchedInput]);
return (
<>
<input type="text" onChange={(e) => setSearchedInput(e.target.value)} />
{searchedInput.length > 0 ? (
searchedItem.length == 0 ? (
<h4>No item found. Sorry bro..</h4>
) : (
searchedItem.map((x, i) => (
<>
<h4>Category: {x.category}</h4>
<span key={i} className="selected-styles">
{x.name}
</span>
</>
))
)
) : (
<>
// SECTION TO OPTIMIZE
<h4>Category: One</h4>
{items
.filter((item) => item.category === "One")
.map((x, i) => (
<span key={i} className="styles">
{x.name}
</span>
))}
<hr />
<h4>Category: Two</h4>
{items
.filter((item) => item.category === "Two")
.map((x, i) => (
<span key={i} className="styles">
{x.name}
</span>
))}
<hr />
<h4>Category: Three</h4>
{items
.filter((item) => item.category === "Three")
.map((x, i) => (
<span key={i} className="styles">
{x.name}
</span>
))}
</>
)}
</>
);
};
export default App;
2
Answers
you could extract the common filter to a separate functional component as the logic is the same for all the cases.
you can write a common functional Component like the one below and pass the filter condition as a parameter.
then replace the duplicated filters and add ItemsFilter components in their place.
modified codesandbox link
you could group the objects if that works, say if its always based off that property. So you can start with some function that takes an array of objects and groups them into an object of arrays, or here I used map as its probably more suited.
Then for the JSX part you can call the function
It’s a bit less code and works for any category. Eventually if you wanted more flexibility in terms of the grouping you can replace key arg with a function that should return the group given the item, but looking at the data you have this seems a good start.
https://codesandbox.io/s/dazzling-swanson-81wufo?file=/src/App.js
Best