Поиск по плоскому списку не возвращает результатов

#react-native #react-native-flatlist #searchbar

#react-native #react-native-плоский список #панель поиска

Вопрос:

Я пытаюсь получить имена хранилищ из вложенного массива, но результатов не получаю, все работает нормально, но когда я набираю в строке поиска, я ничего не получаю (изображение ниже). Я снова вижу плоский список, как только удаляю то, что ввел. Я думаю, что проблема связана с данными, которые я возвращаю из фильтра. Вот что я сделал до сих пор.

 const Purchases = () => {
    const extractKey = ({purchases}) => purchases.toString();
    const [search, setSearch] = useState(content);

    function _searchFilterFunction(searchText, data) {
        let newData = [];
        if (searchText) {
            newData = content.filter(function (item) {
                item.purchases.filter(function (i) {
                    const itemData = i.name.toUpperCase();
                    const textData = searchText.toUpperCase();
                    return itemData.includes(textData);
                })

            });
            setSearch([...newData]);
        } else {
            setSearch([...data]);
        }
    }

    return (
        <View style={styles.container}>

            <TextInput
                style={styles.textInputStyle}
                placeholder="Search by Store"
                onChangeText={(value) => {
                    _searchFilterFunction(value, content);
                }}
            />
         
            <FlatList
                data={search}
                renderItem={renderItem}
                keyExtractor={extractKey}
            />
        </View>
    );
}

  

и вот массив:

 let content = [
    {
        date: 'September 8, 2012',
        total: 754,
        purchases: [
            {
                name: 'Virgin Megastores',
                time: '12:24',
                price: 432,
                icon: vms
            },
            {
                name: 'Apple Store',
                time: '13:43',
                price: 322,
                icon: apple
            }
        ]
    },
    {
        date: 'September 8, 2012',
        total: 754,
        purchases: [
            {
                name: 'Virgin Megastores',
                time: '12:24',
                price: 432,
                icon: vms
            },
            {
                name: 'Apple Store',
                time: '13:43',
                price: 322,
                icon: apple
            }
        ]
    },
]
  

Ответ №1:

Ваша проблема заключается в том, как вы фильтруете свои данные.

 newData = content.filter(function (item) {
    item.purchases.filter(function (i) {
        const itemData = i.name.toUpperCase();
        const textData = searchText.toUpperCase();
        return itemData.includes(textData);
    });
});
  

filter Функция ожидает функцию обратного вызова, которая возвращает логическое значение, чтобы определить, следует ли включать элемент или нет. Поскольку ваш contect.filter вызов ничего не возвращает из своего обратного вызова, конечный newData результат пуст.

Итак, давайте попробуем настроить код на что-то работающее

 newData = content.filter(function (item) {
    // check if any purchase has matches; and keep the filtered results
    const filteredPurchases = item.purchases.filter(function (i) {
        const itemData = i.name.toUpperCase();
        const textData = searchText.toUpperCase();
        return itemData.includes(textData);
    });

    // now let the parent know if it should include this item in the filter
    // if the length is higher than zero, filter will include this item
    return filteredPurchases.length;
});
  

В своем комментарии вы говорите, что хотите показать только применимые покупки. Давайте еще немного скорректируем код. Мы будем map включать в контент только соответствующие покупки, а затем filter все товары с соответствующими покупками

 newData = content.map(function (item) {
    // check if any purchase has matches; and keep the filtered results
    const filteredPurchases = item.purchases.filter(function (i) {
        const itemData = i.name.toUpperCase();
        const textData = searchText.toUpperCase();
        return itemData.includes(textData);
    });

    // now return a newly composed item with only applicable purchases
    return {
      ...item,
      purchases: filteredPurchases
    };
}).filter(function (item) {
   // now only keep items with applicable purchases.
   return item.purchases.length
});
  

Комментарии:

1. Большое вам спасибо, но теперь возникла другая проблема: каждая покупка внутри массива содержимого содержит две покупки, как вы можете видеть, поэтому при поиске я получаю правильный результат в дополнение к другому, потому что массив — это то, что он возвращает. Как я могу получить каждую покупку отдельно?

2. Я немного расширил ответ, добавив для вас дополнительную логику.