[英]render a list using map but filter base on user's query in frontend
I want to achieve this result: https://resepi-khairulaming.vercel.app/我想实现这个结果: https://resepi-khairulaming.vercel.app/
It's easy to just fetch the result from backend by passing the query, but how about doing the filter on the client side?通过传递查询从后端获取结果很容易,但是在客户端做过滤器怎么样? do I need to hold 2 states, eg.
我是否需要保持 2 个状态,例如。
const [data, setData] = useState() // setData from api source on onload const [filteredData setFilteredData] = useState(data)
one is the original source and the another is the filtered source?一个是原始来源,另一个是过滤后的来源? Because the user can clear the query and I have to restore unfiltered data.
因为用户可以清除查询,而我必须恢复未过滤的数据。
is there any better solution than this?还有比这更好的解决方案吗?
You definitely need one state for the semi-persistent API results.对于半持久性 API 结果,您肯定需要一个 state。 For the filtered data to be rendered, having another state like you're thinking is a common option - there's nothing wrong with that.
对于要呈现的过滤数据,像您所想的那样拥有另一个 state 是一个常见的选择 - 这没有任何问题。
Another option is to filter the API data before rendering, without an additional state.另一种选择是在渲染之前过滤 API 数据,而不需要额外的 state。
return (
<div>
{
data
.filter(obj => obj.name.toLowerCase().includes(inputValue.toLowerCase())
.map( /* etc */
Another is to memoize the filtered data, with a dependency array of the state from the API and whatever filters it.另一个是记忆过滤后的数据,使用 API 中的 state 的依赖数组以及任何过滤它的内容。
const [data, setData] = useState([]);
const filteredData = useMemo(
() => data.filter(obj => obj.name.toLowerCase().includes(inputValue.toLowerCase())
[data, inputValue]
);
The inputValue
s and .name
s used above are just examples - replace with whatever your actual filtering mechanism is.上面使用的
inputValue
s 和.name
s 只是示例 - 替换为您实际的过滤机制。
Instead of setting and restoring the filtered state every time when a user tries to search for a value, memorization can be a possible and better option.不是每次用户尝试搜索值时都设置和恢复过滤后的 state,记忆可能是一个可能且更好的选择。
import React, {useState, useMemo} from 'react';
const Home = () => {
const [data, setData] = useState([]);
const [searchVal, setSearchVal] = useState('')
const filteredData = useMemo(() => {
if (searchVal.trim() === '') {
return data;
}
return data.filter(dataItem => dataItem.name === searchVal);
}, [data, searchVal])
// use the filteredData in your list..
}
So you want to optimize the search behaviour.所以你想优化搜索行为。
Here's what I noticed is happening, based on that example you sent and here are some optimization suggestions:根据您发送的示例,这是我注意到的情况,以下是一些优化建议:
keydown
or onchange
event with no delay which may not be the ideal way of doing it.keydown
或onchange
事件上立即触发,没有延迟,这可能不是理想的实现方式。 You want to either throttle
or debounce
in such a case.throttle
或debounce
。 Look these terminologies up. Other resources for you to read on: Full-Text Search (That's what this intended behaviour is called)供您阅读的其他资源:全文搜索(这就是所谓的预期行为)
Suggestion for immediate fix: Make the database call after every onchange (if possible, try to implement debounce to save on API calls, it's easy)立即修复的建议:在每次 onchange 后调用数据库(如果可能,尝试实现去抖以节省 API 调用,这很容易)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.