You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

多选类别筛选FlatList数据实现方案

UI 图片

需求说明

  • 基于顶部类别按钮(支持多选)筛选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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:48:20