Filtering nested React data?
-
How can you correctly filter an array of objects of this kind:
let arr = [{ "category": "new", "list": [{ "item": "Black" }, { "item": "Red" } ] }, { "category": "old", "list": [{ "item": "..." }, { "item": "...." } ] }
So that after filtering, after filtering, to receive such a plan depending on the entered category or item, while if only category is entered, display all item inside, if item is entered, display all categories where this item occurs and the item itself, what would be further in 2- x components could be mapped by category, and then by item. Now I am writing something like this:
сonst filterData = arr .filter( (value) => value.category.toLowerCase().includes(input.value) || value.list.some((i: any) => i.item.toLowerCase().includes(input.value)) ).map(e=>e.list.filter(e=>e.item.toLowerCase().includes(input.value)))
But at the output I get if the input value is empty
[ [{"id":126,"item":"...."},{"id":127,"item":"...."},{"id":133,"item":"....""}], [{"id":129,"item":"...."},{"id":130,"item":"...."}], [{"id":131,"item":"....""},{"id":132,"item":"...."}] ]
JavaScript Anonymous, Feb 8, 2020 -
I would make two dictionaries (datasets):
1. Category name = & gt; Category
2. Item name = & gt; All categories with this Item
Further, when filtering, it will be enough to check for the presence of a key in any dictionary (so you will understand that a category or Item is entered), and return the value by the key.
Dictionaries can be compiled once when receiving data.
Everything written above, provided that I understand correctly that you need JAnonymous -
1. Any line contains an empty string, so this search will return all values.
2.map
adds the result of the passed function to the output array. Since it returns a filtereditems
array for you, you end up with an array ofitems
arrays. If you need categories to return, return categories.
Well, you don't need to do the same work twice, you can do with onereduce
:сonst filterData = filter(arr, input.value);
interface Category {
category: string;
list: Array<{
item: string;
}>;
}
function filter<T extends Category>(data: T[], value: string): T[] {
if (!value) return data.slice(); // или [] если при пустом value нужен пустой массив
value = value.toLowerCase();
return data.reduce((result, category) => {
if(category.category.toLowerCase().includes(value)) {
result.push(category);
} else {
const list = category.list.filter(({ item }) => item.toLowerCase().includes(value));
if (list.length) {
result.push({
...category,
list
});
}
}
return result;
}, [] as T[])
}Anonymous
2 Answers
Your Answer
To place the code, please use CodePen or similar tool. Thanks you!