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