У меня есть компонент DogCardsDisplayed React, который сопоставляется с массивом объектов, который отображает данные в карточках на странице. Мой компонент SearchBar выполняет поиск в массиве и фильтрует список в консоли на основе пользовательского поиска. Как мне применить это к фактическим карточкам, чтобы сами карточки фильтровались на странице.
const dogData = [
{
id: 1,
name: "Hollie",
breed: "Doberman",
age: 3,
weight: 20,
height: 150,
img: "https://placedog.net/500/200?id=61",
},
{
id: 2,
name: "Charles",
breed: "Beagle",
age: 4,
weight: 20,
height: 150,
img: "https://placedog.net/500/200?id=100",
}
import DogCardsDisplayed from "./DogCardsDisplayed";
import dogData from "./dogData";
import { Nav, Navbar, Button } from "react-bootstrap";
function SearchBar() {
const onSub = (e) => {
let substring = e.target.value;
let filteredData = dogData.filter(
(item) =>
item.name.toLowerCase().includes(substring.toLowerCase()) ||
item.breed.toLowerCase().includes(substring.toLowerCase())
);
console.info(filteredData);
};
return (
<Navbar className = "d-block">
<form>
<input
onChange = {onSub}
className = "search-input"
placeholder = "Search"
name = "search"
></input>
<Button
variant = "outline-light"
className = "search-button"
type = "submit"
>
Search
</Button>
</form>
</Navbar>
);
}
function DogCardsDisplayed() {
return dogData.map((item) => (
<Card key = {item.id} className = "card">
<div>
<Card.Img variant = "top" src = {item.img} />
<Card.Body>
<Card.Title>{item.name}</Card.Title>
<div className = "d-flex">
<div><b>Breed:</b> {item.breed}</div>
<div><b>Age:</b> {item.age}</div>
<div><b>Weight:</b> {item.weight}lb</div>
<div><b>Height:</b> {item.height}in</div>
</div>
</Card.Body>
</div>
</Card>
));
}
function SearchPage() {
return (
<>
<SearchBar />
<div className = "d-flex flex-wrap sp-body">
<DogCardsDisplayed />
</div>
</>
);
}
export default SearchPage;
Этого можно добиться, сохранив фильтр в состоянии (useState
)[1], а затем используя useMemo
[2] для возврата отфильтрованных данных на основе изменений в фильтре состояния и dogData
.
function SearchBar({ onSearch }) {
const onSub = (e) => {
onSearch(e.target.value.toLowerCase());
};
return (
<Navbar className = "d-block">
<form>
<input
onChange = {onSub}
className = "search-input"
placeholder = "Search"
name = "search"
/>
</form>
</Navbar>
);
}
function DogCardsDisplayed({ dogData }) {
return dogData.map((item) => (
<Card key = {item.id} className = "card">
<div>
<Card.Img variant = "top" src = {item.img} />
<Card.Body>
<Card.Title>{item.name}</Card.Title>
<div className = "d-flex">
<div><b>Breed:</b> {item.breed}</div>
<div><b>Age:</b> {item.age}</div>
<div><b>Weight:</b> {item.weight}lb</div>
<div><b>Height:</b> {item.height}in</div>
</div>
</Card.Body>
</div>
</Card>
));
}
function SearchPage() {
const [filter, setFilter] = React.useState("");
const filteredData = React.useMemo(() => {
if (filter == "") return dogData;
return dogData.filter(
(item) =>
item.name.toLowerCase().includes(filter) ||
item.breed.toLowerCase().includes(filter)
);
}, [dogData, filter]);
return (
<>
<SearchBar onSearch = {(searchTerm) => setFilter(searchTerm)}/>
<div className = "d-flex flex-wrap sp-body">
<DogCardsDisplayed dogData = {filteredData} />
</div>
</>
);
}
Использованная литература:
[1] Хук useState — https://reactjs.org/docs/hooks-state.html
[2] Хук useMemo — https://reactjs.org/docs/hooks-reference.html#usememo