React实现两级分类联动下拉:选中一级分类后二级下拉加载对应子分类
两级分类联动下拉功能实现方案
原有代码核心问题
- 状态设计混淆:将「子分类选项列表」和「表单选中值」两个完全独立的逻辑存到同一个
sousCategories状态中,初始值设为对象也和后续接口返回的数组类型不匹配 - 状态修改违规:直接对
sousCategories[name]赋值不符合React状态不可变的更新原则 - 渲染逻辑错误:子分类遍历的
map方法没有返回值,且直接输出souscat对象会导致显示异常 - 无效冗余代码:fetch请求配置中存在多余的
data字段
修正后完整代码
import React,{useState,useEffect} from 'react'; import CategorieServices from '../../services/CategorieServices'; function DependentListBetweenCatAndSousCat(props) { // 父分类列表 const [categories, setCategories] = useState([]); // 选中的父分类ID const [selectedCateId, setSelectedCateId] = useState(''); // 子分类列表 const [sousCategories, setSousCategories] = useState([]); // 选中的子分类ID const [selectedSousCateId, setSelectedSousCateId] = useState(''); // 页面加载时拉取所有父分类 useEffect(()=>{ loadcategories(); },[]); const loadcategories = async()=>{ const results = await CategorieServices.categoriesAll("categories/all/"); setCategories(results.data); // 如果有默认选中的父分类,初始化时直接拉取对应子分类 if(props.courseId) { setSelectedCateId(props.courseId) loadSousCategories(props.courseId) } }; // 拉取对应父分类的子分类列表 const loadSousCategories = async (cateId) => { // 切换父分类时先清空原有子分类和选中值 setSousCategories([]) setSelectedSousCateId('') try { const response = await fetch("http://localhost:8000/api/sousCategorie/category/",{ method:"POST", headers:{ "Content-Type":"application/json", }, body: JSON.stringify({ id: cateId }), }) const myJson = await response.json() setSousCategories(myJson) } catch (err) { console.error('子分类拉取失败', err) } } // 父分类切换触发 const selectCategory=(e)=>{ const cateId = e.target.value setSelectedCateId(cateId) loadSousCategories(cateId) }; return ( <div className="selectoption d-flex"> {/* 父分类选择框 */} <select name="categorieName" value={selectedCateId} onChange={selectCategory} > {categories.map((cate)=> <option value={cate.id} key={cate.id}>{cate.name}</option> )} </select> {/* 子分类选择框 */} <select name="sousCategorieName" value={selectedSousCateId} onChange={(e) => setSelectedSousCateId(e.target.value)} > <option value="">-- Choisissez une sous-categorie --</option> {sousCategories.map((souscat)=> ( <option value={souscat.id} key={souscat.id}>{souscat.name}</option> ))} </select> </div> ); } export default DependentListBetweenCatAndSousCat;
关键改动说明
- 拆分了状态:将父分类选中值、子分类列表、子分类选中值拆分为独立状态,逻辑更清晰,避免类型冲突
- 统一使用受控组件写法:通过
value绑定选中状态,替代原生的selected属性,符合React表单开发规范 - 新增子分类拉取逻辑封装,切换父分类时自动清空原有子分类数据,避免旧数据残留
- 修复了子分类遍历渲染的语法问题,补充
key属性,正确展示子分类名称 - 新增异常捕获,避免接口报错导致页面功能异常
内容的提问来源于stack exchange,提问作者Emma Nya
相关产品推荐
相关产品推荐

