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

React Native三级分类选择器实现问询:联动选择与结果存储

我帮你实现了一个符合需求的三级分类选择器,核心思路是用状态维护选中的分类路径和当前展示的分类列表,同时做了面包屑式的指示器支持跳转回溯,代码里还加了详细的注释,你可以直接复用或者按需调整:

React Native 三级分类选择器实现

核心思路

  1. 用 selectedPath 状态存储选中的分类路径(从一级到当前选中的所有层级分类)
  2. 用 currentLevelCategories 状态控制当前展示的分类列表,选中父分类后自动切换到子分类
  3. 指示器列表(面包屑)支持点击回溯到任意已选中的层级
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, FlatList, StyleSheet } from 'react-native';

const CategorySelector = () => {
  // 模拟三级分类数据结构,实际项目可替换为接口返回数据
  const categoryTree = [
    {
      id: 1,
      name: "电子产品",
      children: [
        {
          id: 11,
          name: "手机",
          children: [
            { id: 111, name: "苹果" },
            { id: 112, name: "华为" },
            { id: 113, name: "小米" },
          ],
        },
        {
          id: 12,
          name: "电脑",
          children: [
            { id: 121, name: "笔记本" },
            { id: 122, name: "台式机" },
          ],
        },
      ],
    },
    {
      id: 2,
      name: "服饰",
      children: [
        {
          id: 21,
          name: "男装",
          children: [
            { id: 211, name: "T恤" },
            { id: 212, name: "裤子" },
          ],
        },
        {
          id: 22,
          name: "女装",
          children: [
            { id: 221, name: "连衣裙" },
            { id: 222, name: "外套" },
          ],
        },
      ],
    },
  ];

  // 存储选中的分类路径(从一级到当前选中项)
  const [selectedPath, setSelectedPath] = useState([]);
  // 当前展示的分类列表
  const [currentLevelCategories, setCurrentLevelCategories] = useState(categoryTree);

  // 处理分类项点击
  const handleCategorySelect = (category) => {
    const currentLevel = selectedPath.length;
    // 更新选中路径:替换当前层级的分类,并截断后续已选层级(比如从二级回到一级重新选择)
    const newPath = [...selectedPath.slice(0, currentLevel), category];
    setSelectedPath(newPath);

    // 如果当前分类有子分类,切换到子分类列表;否则清空列表(三级分类无下级)
    if (category.children?.length > 0) {
      setCurrentLevelCategories(category.children);
    } else {
      setCurrentLevelCategories([]);
    }
  };

  // 点击指示器跳转到指定层级
  const navigateToLevel = (level) => {
    const newPath = selectedPath.slice(0, level + 1);
    setSelectedPath(newPath);

    // 回溯找到对应层级的分类列表
    let targetCategories = categoryTree;
    for (let i = 0; i < level; i++) {
      targetCategories = targetCategories.find(cat => cat.id === newPath[i].id).children;
    }
    setCurrentLevelCategories(targetCategories);
  };

  // 渲染选中路径的指示器列表(面包屑)
  const renderIndicatorList = () => {
    return (
      <View style={styles.indicatorContainer}>
        {selectedPath.map((item, index) => (
          <TouchableOpacity
            key={item.id}
            onPress={() => navigateToLevel(index)}
            style={styles.indicatorItem}
          >
            <Text style={styles.indicatorText}>{item.name}</Text>
            {index < selectedPath.length - 1 && (
              <Text style={styles.separator}>></Text>
            )}
          </TouchableOpacity>
        ))}
      </View>
    );
  };

  // 渲染当前层级的分类列表
  const renderCategoryList = () => {
    if (currentLevelCategories.length === 0) {
      return (
        <View style={styles.emptyContainer}>
          <Text style={styles.emptyText}>已选择到最细分的分类~</Text>
        </View>
      );
    }

    return (
      <FlatList
        data={currentLevelCategories}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <TouchableOpacity
            style={styles.categoryItem}
            onPress={() => handleCategorySelect(item)}
          >
            <Text style={styles.categoryText}>{item.name}</Text>
            {/* 有子分类时显示箭头提示 */}
            {item.children?.length > 0 && (
              <Text style={styles.arrowIcon}>></Text>
            )}
          </TouchableOpacity>
        )}
      />
    );
  };

  return (
    <View style={styles.container}>
      {renderIndicatorList()}
      {renderCategoryList()}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#fff',
  },
  indicatorContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    marginBottom: 20,
    paddingVertical: 8,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0',
  },
  indicatorItem: {
    flexDirection: 'row',
    alignItems: 'center',
    marginRight: 10,
  },
  indicatorText: {
    fontSize: 16,
    color: '#1677ff',
  },
  separator: {
    marginHorizontal: 4,
    color: '#999',
  },
  categoryItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0',
  },
  categoryText: {
    fontSize: 18,
    color: '#333',
  },
  arrowIcon: {
    fontSize: 18,
    color: '#999',
  },
  emptyContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  emptyText: {
    fontSize: 16,
    color: '#999',
  },
});

export default CategorySelector;

关键细节说明

  • 状态管理:selectedPath 就是你需要的“所有选中的分类及子分类”状态,直接可以用来做提交或其他业务逻辑
  • 层级跳转:点击指示器上的任意分类,会自动回溯到对应层级的分类列表,操作流畅
  • 扩展性:如果后续需要扩展更多层级,只需要修改分类数据结构即可,核心逻辑无需改动
  • 样式自定义:所有样式都集中在 StyleSheet 里,可以根据你的UI设计自由调整

内容的提问来源于stack exchange,提问作者MGalmostcoder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:10:40