带有 React Hook 的多个过滤器 - 链接功能

Multiple filters with React Hook - Chaining function

您好,我创建了一个带有多重过滤器的搜索栏,它可以工作,但功能之间过于依赖。这里的问题是函数正在处理多种情况。 是否可以通过链接它们来减轻每个功能以及如何?我真的不知道链接方法。 谢谢

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;

SandBox Sample 您可以像这样进行第一轮简化:

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]);

更惯用的方法是使用 momoisation 挂钩。即删除 sortedAnimes 作为状态和

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]);

试试这个

如果你在 jsx 中使用 filter 方法那么你试试这个方法。

让我简单介绍一下, 将 userInfo 视为包含名称、电子邮件、位置等字段的对象。因此,如果您希望过滤器方法根据这些字段值提供搜索结果,那么您可以在 jsx 中使用类似的东西。

    {userInfo.filter((user) => (
                                    
                        user.name.toLowerCase().includes(cloneSearchTerm)
                        ||
                        user.email.toLowerCase().includes(cloneSearchTerm)
                        ||
                        user.location.toLowerCase().includes(cloneSearchTerm)
                    )
    
                    ).map((user, idx) => (
                        <div key={idx}>
                                <span>{user.name}</span>
                                <span>{user.email}</span>
                                <span>{user.location}</span>
                        </div>

                    ))}