React Native中如何通过多选数组类别筛选FlatList数据
多选类别筛选FlatList数据实现方案

需求说明
- 基于顶部类别按钮(支持多选)筛选FlatList中的酒店数据
- 酒店数据来自
HotelData数组,顶部类别通过categories数组渲染在横向ScrollView中
原数据定义
const HotelData = [ { id: '1', img: require('../Assets/UIPracticeImage/H1.jpg'), name: 'Chef Vincent', desc: 'Lorem ipsum dolor sit amet aliquon sciscilant', tag: 'Toutes possibilities', compareKey: 1, }, { id: '2', img: require('../Assets/UIPracticeImage/H2.jpg'), name: 'Pine hill green caben', desc: 'Lorem ipsum dolor sit amet aliquon sciscilant', tag: 'Restaurants', compareKey: 2, }, { id: '3', img: require('../Assets/UIPracticeImage/H3.jpg'), name: 'Sky Palace', desc: 'Lorem ipsum dolor sit amet aliquon sciscilant', tag: 'Restaurants', compareKey: 2, }, { id: '4', img: require('../Assets/UIPracticeImage/H4.jpg'), name: 'Green leaf', desc: 'Lorem ipsum dolor sit amet aliquon sciscilant', tag: 'Toutes possibilities', compareKey: 1, }, { id: '5', img: require('../Assets/UIPracticeImage/H1.jpg'), name: 'Pine green leaf', desc: 'Lorem ipsum dolor sit amet aliquon sciscilant', tag: 'Bars', compareKey: 3, }, ]; const [categories, setCategories] = useState([ {name: 'Toutes possibilités', key: 1, isCheck: false, compareKey: 1}, {name: 'Restaurantes', key: 2, isCheck: false, compareKey: 2}, {name: 'Bars', key: 3, isCheck: false, compareKey: 3}, ]);
完整实现代码
1. 新增状态与核心逻辑
import { useState } from 'react'; import { View, ScrollView, TouchableOpacity, Text, FlatList, Image, StyleSheet } from 'react-native'; // ... 原HotelData和categories定义 ... const [selectedKeys, setSelectedKeys] = useState([]); // 切换类别选中状态 const handleCategoryToggle = (targetKey) => { // 更新categories的选中标记 const updatedCategories = categories.map(category => { if (category.compareKey === targetKey) { return { ...category, isCheck: !category.isCheck }; } return category; }); setCategories(updatedCategories); // 更新选中的类别key数组 setSelectedKeys(prev => { if (prev.includes(targetKey)) { return prev.filter(key => key !== targetKey); } else { return [...prev, targetKey]; } }); }; // 筛选数据:选中为空时显示全部,否则显示匹配项 const filteredHotels = selectedKeys.length === 0 ? HotelData : HotelData.filter(hotel => selectedKeys.includes(hotel.compareKey));
2. 渲染UI组件
return ( <View style={styles.container}> {/* 顶部类别筛选栏 */} <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.categoryScroll} > {categories.map(category => ( <TouchableOpacity key={category.key} style={[ styles.categoryBtn, category.isCheck && styles.categoryBtnActive ]} onPress={() => handleCategoryToggle(category.compareKey)} > <Text style={[ styles.categoryText, category.isCheck && styles.categoryTextActive ]}> {category.name} </Text> </TouchableOpacity> ))} </ScrollView> {/* 酒店列表 */} <FlatList data={filteredHotels} keyExtractor={item => item.id} style={styles.hotelList} renderItem={({ item }) => ( <View style={styles.hotelItem}> <Image source={item.img} style={styles.hotelImg} /> <View style={styles.hotelInfo}> <Text style={styles.hotelName}>{item.name}</Text> <Text style={styles.hotelDesc}>{item.desc}</Text> <Text style={styles.hotelTag}>{item.tag}</Text> </View> </View> )} /> </View> );
3. 样式定义
const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, categoryScroll: { paddingVertical: 12, paddingHorizontal: 16, borderBottomWidth: 1, borderBottomColor: '#f0f0f0', }, categoryBtn: { paddingHorizontal: 18, paddingVertical: 8, borderRadius: 20, backgroundColor: '#f5f5f5', marginRight: 12, }, categoryBtnActive: { backgroundColor: '#007AFF', }, categoryText: { fontSize: 14, color: '#333', }, categoryTextActive: { color: '#fff', }, hotelList: { flex: 1, }, hotelItem: { flexDirection: 'row', padding: 16, borderBottomWidth: 1, borderBottomColor: '#f8f8f8', }, hotelImg: { width: 80, height: 80, borderRadius: 8, resizeMode: 'cover', }, hotelInfo: { flex: 1, marginLeft: 12, justifyContent: 'center', }, hotelName: { fontSize: 16, fontWeight: '500', marginBottom: 4, }, hotelDesc: { fontSize: 12, color: '#666', marginBottom: 4, lineHeight: 16, }, hotelTag: { fontSize: 12, color: '#007AFF', }, });
关键说明
- 用
selectedKeys数组跟踪选中的类别,避免每次筛选都遍历categories,提升性能 - 点击类别按钮时同步更新
categories的isCheck状态和selectedKeys数组,确保状态一致 - 筛选逻辑兼容默认状态:未选中任何类别时显示全部酒店数据
- 通过样式区分选中/未选中状态,让用户直观看到当前筛选条件
内容的提问来源于stack exchange,提问作者Dhyana Dave
相关产品推荐
相关产品推荐

