Как искать и фильтровать в массиве объектов на setState - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь создать поиск на основе массива объектов с реакцией, данные в этом формате:

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, чтобы иметь возможность соответствующим образом отображать данные chnage:

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>
)}

Есть идеи для меня? Большое спасибо за ваше руководство!

1 Ответ

1 голос
/ 19 июня 2020

Думаю, это то, что вы ищете. Я создал следующие утилиты для фильтрации в соответствии с вашими требованиями.

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"))

Надеюсь, это поможет.

...