首页 > 解决方案 > 如何在 setState 上的对象数组中搜索和过滤

问题描述

我正在尝试创建一个基于对象数组的搜索,并对哪些数据采用这种格式做出反应:

const data =  [
  {"category 1" : [
    {
        "name": "Orange",
        "desc": "juice, orange, Water"
    },
    { 
        "name": "Ananas",
        "desc": "juice, ananas, water"
    }
  ]
  },
  {"category 2" : [
    {
        "name": "Banana Split",
        "desc": "Banana, ice cream, chocolat, topping",
        "allergens": "nuts"
    },
    {
        "name": "Mango Sticky Rice",
        "desc": "Mango, rice, milk",
        "allergens": ""
    }
  ]
  }
]

我将此数据存储在 useState 声明中,以便能够在数据更改时相应地呈现:

const [filteredBySearch, setFilteredBySearch] = useState(data)

我有一个输入,我们可以在其中输入任何内容并在 useState 声明中进行设置。

目标:

如果我输入我的输入:

"Jui"

输出应该是:

console.log(filteredBySearch)
/* output: 
[
  {"category 1" : [
    {
        "name": "Orange",
        "desc": "juice, orange, Water"
    },
    { 
        "name": "Ananas",
        "desc": "juice, ananas, water"
    }
  ]
  },
  {"category 2" : []
  }
]*/

示例 2: 如果我输入我的输入:

"Orange banana"

输出应该是:

console.log(filteredBySearch)
/* output:  [
  {"category 1" : [
    {
        "name": "Orange",
        "desc": "juice, orange, Water"
    }
  ]
  },
  {"category 2" : [
    {
        "name": "Banana Split",
        "desc": "Banana, ice cream, chocolat, topping",
        "allergens": "nuts"
    }
  ]
  }
]*/

我尝试使用地图和过滤器创建一个新对象,并使用 setFilteredBySearch 设置它,但我什么也得不到,即使创建这个新对象也是如此。

这是完整的组件:

import Card from '../components/Card'
import React, { useState } from 'react';


export default function IndexPage({ data, search }) {

    //search is the result of input value set on a useState

    //Filter categoriesFoods by search
    const [FilteredBySearch, setFilteredBySearch] = useState(data)



    return (
        <div className="main-content">
            <div className="card-container">
                {
                    FilteredBySearch.map(function(el, i) {
                        return (
                            <div key={i}>
                                <h2 className="category" id={Object.keys(el)}>{Object.keys(el)}</h2>
                                {
                                    el[Object.keys(el)].map (function(itm,index){
                                        return <Card key={index} infoItem={itm}/>
                                    })
                                }
                            </div>
                        )
                    })
                }
            </div>

            <style jsx>{`...`}</style>
        </div>
)}

对我有什么想法吗?非常感谢您的指导!

标签: arraysreactjsobjectfiltersetstate

解决方案


我想这就是你要找的。我根据您的要求创建了以下过滤实用程序。

const dataObj = [
  {
    'category 1': [
      {
        name: 'Orange',
        desc: 'juice, orange, Water',
      },
      {
        name: 'Ananas',
        desc: 'juice, ananas, water',
      },
    ],
  },
  {
    'category 2': [
      {
        name: 'Banana Split',
        desc: 'Banana, ice cream, chocolat, topping',
        allergens: 'nuts',
      },
      {
        name: 'Mango Sticky Rice',
        desc: 'Mango, rice, milk',
        allergens: '',
      },
    ],
  },
]


const checkIfInputMatches = (input, desc) => input.toLowerCase().split(" ").some(o => desc.toLowerCase().includes(o))

const filterByInput = (data, input) => {
  let finalResult = [];
  data.forEach(d => { 
    let keys = Object.keys(d);
    let values = Object.values(d);
    finalResult = [...finalResult, ...values.map((obj, index) => {
     let result = obj.filter(o => checkIfInputMatches(input, o.desc))
     return  {[keys[index]]: result}
    })]
  })
  return finalResult
}

console.log(filterByInput(dataObj, 'JUI'))
console.log(filterByInput(dataObj, "orange"))
console.log(filterByInput(dataObj, "rice"))
console.log(filterByInput(dataObj, "Orange banana"))

希望这可以帮助。


推荐阅读