【问题标题】:Filter array based on multiple filters基于多个过滤器的过滤器阵列
【发布时间】:2021-01-12 23:21:45
【问题描述】:

我有一个表,我希望能够对其应用多个过滤器。我当前的代码将按电子邮件或状态进行过滤,但我希望它同时执行这两种操作,以便用户可以优化结果。

我尝试在filteredInvoices 变量中添加&& 而不是||

我允许用户选择他们想要使用的过滤器并将其存储在 useState 中的对象中。如果过滤器处于活动或非活动状态,我也会跟踪状态。

const [filter, setFilter] = useState({active: false})

用户选择过滤器的过滤器对象如下所示:

filter: {active: true, customerEmail: 'johndoe@gmail.com', status: 'open'}

当用户将此过滤器应用于表时,当过滤器更改时,我会在 useEffect 中调用一个名为 updateFilter() 的函数。然后,这会将过滤后的数组设置为状态,然后在 return 中迭代。

const updateFilter = () => {
    const filteredInvoices = invoices.filter((inv) => {
        const emailMatch = filter.customerEmail && inv.customerEmail.toLowerCase().includes(filter.customerEmail.toLowerCase())
        const statusMatch = inv.status === filter.status
        return emailMatch || statusMatch
    })
    setListToRender(filteredInvoices)
}

useEffect(() => {
    if (filter.active) {
        updateFilter()
    }

}, [filter])

被过滤的状态是一个对象数组。

如何通过添加到过滤器对象中的多个条件进行过滤?

是否有一个通用的设计可以让我向过滤器对象添加额外的过滤器并且它也可以工作?

例如 - johndoe@gmail.com 有 10 张发票 - 3 张未结,4 张已付款,3 张作废。如果过滤器对象如下所示:

如何过滤以仅显示该客户的未结发票。

提前感谢您的任何建议!

【问题讨论】:

    标签: javascript arrays reactjs filter


    【解决方案1】:

    由于您不仅希望能够匹配特定的键值对,而且可能还需要在过滤之前对值进行预处理(就像您将电子邮件转换为小写一样),然后是通用的方法可能最适合您。你可以有这样的东西

    const updateFilter = () => {
        const filteredInvoices = invoices.filter(invoice => {
        let validInvoice = true;
        
        for (const [key, value] of Object.entries(filter)) {
          if (Array.isArray(value)) {
            if (!value.includes(invoice[key])) {
              validInvoice = false;
            }
          }
          else if (typeof value === 'function') {
            if (!value(invoice[key])) {
              validInvoice = false;
            }
          }
          else {
            if (value !== invoice[key]) validInvoice = false;
          }
        }
        
        return validInvoice;
      });
      
      setListToRender(filteredInvoices)
    }
    

    使用这种方法,您可以拥有一个包含原始值、函数或数组的过滤器。像这样:

    const filter = {
        // This will check if the invoice 'active' property is true
        active: true,
        // This will check that the status is NOT equal to pending
        status: (status) => status !== 'pending',
        // This will check if the email matches ANY of these values
        email: ['john@doe.com', 'cho@mumma.com']
    };
    

    这种方法比简单的键/值匹配方法有更多的细微差别,并且可以让您更深入地自定义过滤器

    【讨论】:

      【解决方案2】:

      您可以使用filterevery 数组方法进行过滤。

      const invoices = [
       {active: false , customerEmail: 'joedoe@gmail.com', status: 'paid'},
       {active: false , customerEmail: 'sam@gmail.com', status: 'paid'},
       {active: true , customerEmail: 'michael@gmail.com', status: 'void'},
       {active: true , customerEmail: 'adam@gmail.com', status: 'paid'}, 
       {active: true , customerEmail: 'johndoe@gmail.com', status: 'open'}
      ]
      
      const filter = {active: true, customerEmail: 'johndoe@gmail.com', status: 'open'}
      
      const selectedFilterKeys = Object.keys(filter)
      
      const filteredInvoices = invoices.filter(invoice => selectedFilterKeys.every(key => 
            filter[key] === invoice[key]
      ))
      
      console.log("filteredInvoices", filteredInvoices)

      【讨论】:

        【解决方案3】:

        概述

        过滤通常作为对后端服务的 API 请求性能更高,但在前端完全可行。我还认为您希望这发生在一个事件上,而不是在useEffect 内。话虽如此,这里有几个过滤选项。

        选项 1

        为发票对象上的每个可过滤属性添加条件。

        const filteredInvoices = invoices.filter((inv) => {
          const isEmailMatch = inv.customerEmail.toLowerCase() === filter.customerEmail.toLowerCase();
          const isStatusMatch = inv.status === filter.status;
        
          // Add other matches here.
        
          return isEmailMatch && isStatusMatch;
         });
        

        选项 2

        这需要从filter 状态中提取status。在我看来,这个解决方案更具可扩展性。

        const [active, setActive] = useState(false); // Extracting active.
        const [filter, setFilter] = useState({});
        
        const updateFilter = () => {
          const filteredInvoices = invoices.filter((item) => {
            for (const key in filter) {
              if (item[key] === undefined || item[key] !== filter[key])
                return false;
            }
            return true;
          });
        };
        
        useEffect(() => {
          if (active) updateFilter();
        }, [filter]);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-13
          • 1970-01-01
          • 2020-06-18
          • 1970-01-01
          • 1970-01-01
          • 2021-12-12
          相关资源
          最近更新 更多