Несколько фильтров с функцией React Hook - Chaining - PullRequest
1 голос
/ 19 сентября 2019

Здравствуйте. Я создал панель поиска с фильтром multipl, он работает, но функции слишком зависят друг от друга.Проблема здесь в том, что функции обрабатывают несколько случаев.Можно ли будет облегчить каждую функцию путем их цепочки и как?Я действительно не понимаю метод цепочки.спасибо

import React, { useState, useEffect } from "react";
import Search from "./Search";
import Anime from "./Anime";
import "./App.css";

const KIJAN_API_URL = "https://api.jikan.moe/v3/top/anime/1/upcoming";
const App = () => {
  const [animes, setAnimes] = useState([]);
  const [sortedAnimes, setSortedAnimes] = useState([]);
  const [searchValue, setSearchValue] = useState("")
  const [filterByType, setFilterByType] = useState("");
  const [filterByYear, setFilterByYear] = useState("");

  useEffect(() => {
    fetch(KIJAN_API_URL)
      .then(response => {
        if (response.ok) {
          return response.json();
        } else {
          throw new Error("Something went wrong");
        }
      })
      .then(jsonResponse => {
        setAnimes(jsonResponse.top);
      })
      .catch(error => {
        console.log(error);
      });
  }, []);

  useEffect(() => {

    const callFilterByType = result => {
      if (filterByType === "") {
        callFilterByYear(result);
        console.log(result);
      } else {
        result = result.filter(anime => anime.type === filterByType);
        callFilterByYear(result);
        console.log(result);
      }
    };

    const callFilterByYear = result => {
      if (filterByYear === "") {
        setSortedAnimes(result);
      } else {
        const regex = new RegExp(`${filterByYear}`, "gi");
        result = result.filter(anime => regex.test(anime.start_date));
        setSortedAnimes(result);
        console.log(result);
      }
    };

    if (searchValue === "") {
      callFilterByType(animes);
    } else {
      const regex = new RegExp(`${searchValue}`, "gi");
      console.log("search : ", searchValue);
      const result = animes.filter(anime => regex.test(anime.title));
      callFilterByType(result);
      console.log(result);
    }


  }, [searchValue, animes, filterByType, filterByYear]);

  return (
    <div className="App">
      <Search
        searchValue={searchValue}
        setSearchValue={setSearchValue}
        filterByType={filterByType}
        setFilterByType={setFilterByType}
        filterByYear={filterByYear}
        setFilterByYear={setFilterByYear}
      />
      {sortedAnimes.length > 0 ? (
        sortedAnimes.map((anime, index) => {
          return <Anime key={index} anime={anime} />;
        })
      ) : (
        <span>Aucune correspondance</span>
      )}
    </div>
  );
};

export default App;

1 Ответ

0 голосов
/ 20 сентября 2019

Образец SandBox Вы можете выполнить первый раунд упрощения следующим образом:

useEffect(() => {
    let result = [...animes];

    if(searchValue) {
      const searchRegex = new RegExp(`${searchValue}`, "gi");
      result = result.filter(anime => searchRegex.test(anime.title));      
    }

    if(filterByType) {
      result = result.filter(anime => anime.type === filterByType);      
    }

    if(filterByYear) {
      const yearRegex = new RegExp(`${filterByYear}`, "gi");
      result = result.filter(anime => yearRegex.test(anime.start_date));
    }
    setSortedAnimes(result);

}, [searchValue, animes, filterByType, filterByYear]);

Его можно уменьшить до более компактной формы, например:

useEffect(() => {
    const searchRegex = searchValue && new RegExp(`${searchValue}`, "gi");
    const yearRegex = filterByYear && new RegExp(`${filterByYear}`, "gi");
    const result = animes.filter(anime => 
      (!searchRegex || searchRegex.test(anime.title)) &&
      (!filterByType || anime.type === filterByType)) &&
      (!yearRegex || yearRegex.test(anime.start_date))
    )
    setSortedAnimes(result);
}, [searchValue, animes, filterByType, filterByYear]);

Более идиоматическим способом было бы использовать использование крюка для умозаключений.т.е. удалить отсортированные аниме как состояние и

const sortedAnimes = useMemo(() => {
    const searchRegex = searchValue && new RegExp(`${searchValue}`, "gi");
    const yearRegex = filterByYear && new RegExp(`${filterByYear}`, "gi");
    return animes.filter(anime => 
      (!searchRegex || searchRegex.test(anime.title)) &&
      (!filterByType || anime.type === filterByType)) &&
      (!yearRegex || yearRegex.test(anime.start_date))
    )
}, [searchValue, animes, filterByType, filterByYear]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...