简体   繁体   English

使用 map 呈现列表,但根据用户在前端的查询进行过滤

[英]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:根据您发送的示例,这是我注意到的情况,以下是一些优化建议:

  1. The search is immediately triggered on the keydown or onchange event with no delay which may not be the ideal way of doing it.搜索会在keydownonchange事件上立即触发,没有延迟,这可能不是理想的实现方式。 You want to either throttle or debounce in such a case.在这种情况下,您想要throttledebounce Look these terminologies up.查找这些术语。 They will save you multiple API calls.他们将为您节省多个 API 电话。 What they will help do is run the API query, only when the user stops typing for an X amount of time, otherwise don't.他们将帮助做的是运行 API 查询,仅当用户停止输入 X 时间时,否则不要。
  2. It's an API call to a database.这是对数据库的 API 调用。 In production, you may want to use ElasticSearch or a search engine which stores indexes in memory.在生产中,您可能希望使用 ElasticSearch 或在 memory 中存储索引的搜索引擎。
  3. You could also cache most searched results and first hit the cache, if missed, then query database.您还可以缓存大多数搜索结果并首先命中缓存,如果未命中,则查询数据库。 Options: Redis, Memcached, ElastiCache, ElasticSearch.选项:Redis、Memcached、ElastiCache、ElasticSearch。
  4. Holding the data in a state is not a good option, unless the number of records is less.将数据保存在 state 中不是一个好的选择,除非记录数更少。 If it goes into thousands, you wouldn't want to make such an expensive call to your database and then hold that.如果它达到数千,你不会想对你的数据库进行如此昂贵的调用然后保持它。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM