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

#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