#reactjs #object #filter #react-hooks #state
#reactjs #объект #Фильтр #реагирующие хуки #состояние
Вопрос:
У меня есть отображаемый компонент React, который отображает массив объектов, отображающий данные в карточках на странице. Мой компонент панели поиска выполняет поиск по массиву и фильтрует список в консоли на основе пользовательского поиска. Как мне применить это к фактическим картам, чтобы сами карты фильтровались на странице.
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.log(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;
Ответ №1:
Вы можете добиться этого, сохранив фильтр в state ( 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 hook — https://reactjs.org/docs/hooks-state.html
[2] useMemo hook — https://reactjs.org/docs/hooks-reference.html#usememo