我有一个表,希望对其应用多个过滤器。我当前的代码将按电子邮件或状态进行过滤,但我希望两者同时执行,以便用户优化结果。
我尝试在&&
变量中添加||
而不是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张作废。如果过滤器对象如下所示:
如何过滤以仅显示该未清客户的发票。
提前感谢您的任何建议!
答案 0 :(得分:2)
由于您不仅希望能够匹配特定的键值对,而且可能还需要做一些诸如在过滤之前对值进行预处理(例如将电子邮件转换为小写字母的操作),然后再进行通用操作方法可能最适合您。你可以有这样的东西
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']
};
与简单的键/值匹配方法相比,此方法可带来更多细微差别,并使您可以更深入地自定义过滤器
答案 1 :(得分:1)
您可以使用filter
和every
数组方法进行过滤。
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)
答案 2 :(得分:0)
作为对后端服务的API请求,筛选通常更有效,但完全可以在前端执行。我还认为您希望在事件而不是useEffect
内发生这种情况。话虽这么说,这里有两个过滤选项。
为发票对象上的每个可过滤属性添加条件。
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;
});
这将需要从status
状态中提取filter
。我认为该解决方案更具可扩展性。
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]);