0

I'm trying to create a search based on an array of objects with react which data is in this format:

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": ""
    }
  ]
  }
]

I stored this data inside useState declaration to be able to render accordingly on data chnage:

const [filteredBySearch, setFilteredBySearch] = useState(data)

I have an input where we can type anything and set inside useState declaration.

Goal:

If I type in my input:

"Jui"

Output should be:

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

Exemple 2: If I type in my input:

"Orange banana"

Output should be:

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"
    }
  ]
  }
]*/

I've try creating a new object with map and filter and set it with setFilteredBySearch, but I can't get anything, even creating this new object.

This the full component:

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

Any idea for me ? Thanks a lot for your guidance!

3
  • Posting your full component code would help people to understand what are you trying to achieve. Commented Jun 19, 2020 at 11:18
  • Thx @Jagan, it's done Commented Jun 19, 2020 at 11:35
  • @Jagan feel free to remove your unvote or tell me if any other information is required. Thx Commented Jun 19, 2020 at 13:55

1 Answer 1

1

I think this is what you are looking for. I have created below utilities for filtering as per your requirement.

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

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.