I am working on a React project. I am trying to implement search functionality. So far, everything is working as I expect, but what I am looking for exactly is to display the filtered data only if the user clicks on a "Search" btn next to the input field, and not to display the data once the user begins to type something on the input. Here is the code of 2 relevant components , UsersHeader being the child of Users:
function Users() {
const [filteredResults, setFilteredResults] = React.useState([]);
const [searchInput, setSearchInput] = React.useState("");
const searchItems = (searchValue) => {
setSearchInput(searchValue);
if (searchInput !== "") {
const filteredData = UsersCollection.filter((user) => {
return (
Object.values(user.userName)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.email)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.country)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.company)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.registrationDate)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase())
);
});
setFilteredResults(filteredData);
} else {
setFilteredResults(UsersCollection);
}
};
return (
<div style={{ padding: "100px 100px 100px 300px" }}>
<div>
<UsersHeader {...{ searchItems, searchInput }}></UsersHeader>
</div>
<div>
{searchInput?.length >= 1 ? ( //if something is being typed in the search input field
<UserList filteredResults={filteredResults} />
) : (
<UserList
searchInput={searchInput}
UsersCollection={UsersCollection}
></UserList>
)}
</div>
</div>
);
}
export default Users;
export function UsersHeader({ searchItems }) {
const [searchValue, setSearchValue] = useState();
const handleChange = (e) => {
// setSearchValue(e.target.value);
searchItems(e.target.value);
};
const handlePressEnter = () => {
handleClick();
};
const handleClick = () => {};
return (
<div className="user-header">
<div>
<Button
className="user-header-filter-btn"
style={{ width: "fit-content", height: "fit-content" }}
>
<img src={filterIcon} alt="" />
</Button>
</div>
<div>
<Input
value={searchValue}
onChange={(e) => {
searchItems(e.target.value);
}}
className="user-header-input"
style={{ width: "800px" }}
placeholder=" Search by keyword"
allowClear
onPressEnter={(e) => {
handlePressEnter(e);
}}
/>
</div>
<div>
<Button onClick={handleClick} className="user-header-search-btn">
<Search />
<span>Search</span>
</Button>
</div>
</div>
);
}
CodePudding user response:
Your Problem is that you're returning the filter on typing. what you should do is remove the code that is responsible for returning filtered messages into a separate function that is triggered at the click of the search button.
const handleChange = (e) => {
setSearchInput(e.target.value);
//searchItems(e.target.value);
};
const searchItems = () => {
//setSearchInput(searchValue);
if (searchInput !== "") {
const filteredData = UsersCollection.filter((user) => {
return (
Object.values(user.userName)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.email)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.country)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.company)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase()) ||
Object.values(user.registrationDate)
.join("")
.toLowerCase()
.includes(searchInput.toString().toLowerCase())
);
});
setFilteredResults(filteredData);
} else {
setFilteredResults(UsersCollection);
}}
const handleClick = () => {searchItems()};