Как создать адаптивный поисковый фильтр с помощью React

У меня есть компонент 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;

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
1 264
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Этого можно добиться, сохранив фильтр в состоянии (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

Другие вопросы по теме