Answer the question
In order to leave comments, you need to log in
Filtering nested React data?
How can one correctly filter an array of objects of such a plan:
let arr = [{
"category": "new",
"list": [{
"item": "Black"
},
{
"item": "Red"
}
]
},
{
"category": "old",
"list": [{
"item": "..."
},
{
"item": "...."
}
]
}
с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)))
[
[{"id":126,"item":"...."},{"id":127,"item":"...."},{"id":133,"item":"....""}],
[{"id":129,"item":"...."},{"id":130,"item":"...."}],
[{"id":131,"item":"....""},{"id":132,"item":"...."}]
]
Answer the question
In order to leave comments, you need to log in
I would make two dictionaries (sets of data correspondences):
1. Category name => Category
2. Item name => All categories with this Item
Next, when filtering, it will be enough to check for the presence of a key in any dictionary (this way you will understand if a category or Item is entered), and return value by key.
Dictionaries can be compiled once when data is received.
Everything written above, provided that I correctly understood what you need J
1. An empty string occurs in any line, so such a search returns all values.
2. map
Adds the result of the passed function into the output array. Since it returns a filtered array items
for you, you end up with an array of arrays items
. If you need categories to be returned, return categories.
Well, you don’t need to do the same job twice, you can get by with one reduce
:
с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[])
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question