React JS实现下拉框联动:根据性别筛选对应姓名
React多组联动下拉框实现方案
原代码问题梳理
- 状态命名混淆:
name状态实际存储的是性别ID,易引发误解 - 直接在组件体调用
setState:会触发无限重渲染 - 多组下拉框共用同一状态:各组选中值会互相干扰
- 性别下拉框显示不直观:直接展示数字ID而非“Male/Female”文本
- 无联动过滤逻辑:姓名下拉框未根据选中性别筛选选项
修正后的完整代码
import React, { useState } from 'react'; import { Box, TextField, MenuItem } from '@mui/material'; // 原始人员数据(放在组件外部避免重复创建) const personData = [ { Field_ID: 1, FieldName_CR: "Sohan", gender_ID: 1, male: "Male" }, { Field_ID: 2, FieldName_CR: "Mohan", gender_ID: 1, male: "Male" }, { Field_ID: 3, FieldName_CR: "Gaurav", gender_ID: 1, male: "Male" }, { Field_ID: 4, FieldName_CR: "Hakim", gender_ID: 1, male: "Male" }, { Field_ID: 5, FieldName_CR: "Sumit", gender_ID: 1, male: "Male" }, { Field_ID: 9, FieldName_CR: "Neha", gender_ID: 2, female: "Female" }, { Field_ID: 10, FieldName_CR: "Seema", gender_ID: 2, female: "Female" }, { Field_ID: 11, FieldName_CR: "Anuradha", gender_ID: 2, female: "Female" }, { Field_ID: 12, FieldName_CR: "Meenu", gender_ID: 2, female: "Female" }, { Field_ID: 13, FieldName_CR: "Harsha", gender_ID: 2, female: "Female" } ]; // 整理后的性别选项(关联ID与显示文本) const genderOptions = [ { id: 1, label: 'Male' }, { id: 2, label: 'Female' } ]; const MultiGroupDropdown = () => { // 初始化两组下拉框的独立状态,每组维护自己的性别和姓名选中值 const [groups, setGroups] = useState([ { gender: '', name: '' }, { gender: '', name: '' } ]); // 处理下拉框值变化的通用函数 const handleGroupChange = (groupIndex, field, value) => { const updatedGroups = [...groups]; updatedGroups[groupIndex][field] = value; // 切换性别时清空对应组的姓名选择,避免无效值残留 if (field === 'gender') { updatedGroups[groupIndex].name = ''; } setGroups(updatedGroups); }; return ( <> {/* 第一组下拉框 */} <Box sx={{ display: 'flex', gap: 2, marginBottom: 2 }}> <TextField className="ruleContainer" select label="Gender" variant="outlined" size="small" value={groups[0].gender} onChange={(e) => handleGroupChange(0, 'gender', e.target.value)} > <MenuItem value="">请选择性别</MenuItem> {genderOptions.map(opt => ( <MenuItem key={opt.id} value={opt.id}> {opt.label} </MenuItem> ))} </TextField> <TextField className="ruleContainer" select label="Name" variant="outlined" size="small" value={groups[0].name} onChange={(e) => handleGroupChange(0, 'name', e.target.value)} disabled={!groups[0].gender} {/* 未选性别时禁用姓名框 */} > <MenuItem value="">请选择姓名</MenuItem> {/* 根据选中的性别过滤姓名选项 */} {personData .filter(person => person.gender_ID === groups[0].gender) .map(person => ( <MenuItem key={person.Field_ID} value={person.FieldName_CR}> {person.FieldName_CR} </MenuItem> ))} </TextField> </Box> {/* 第二组下拉框 */} <Box sx={{ display: 'flex', gap: 2 }}> <TextField className="ruleContainer" select label="Gender" variant="outlined" size="small" value={groups[1].gender} onChange={(e) => handleGroupChange(1, 'gender', e.target.value)} > <MenuItem value="">请选择性别</MenuItem> {genderOptions.map(opt => ( <MenuItem key={opt.id} value={opt.id}> {opt.label} </MenuItem> ))} </TextField> <TextField className="ruleContainer" select label="Name" variant="outlined" size="small" value={groups[1].name} onChange={(e) => handleGroupChange(1, 'name', e.target.value)} disabled={!groups[1].gender} > <MenuItem value="">请选择姓名</MenuItem> {personData .filter(person => person.gender_ID === groups[1].gender) .map(person => ( <MenuItem key={person.Field_ID} value={person.FieldName_CR}> {person.FieldName_CR} </MenuItem> ))} </TextField> </Box> </> ); }; export default MultiGroupDropdown;
关键改动说明
- 独立状态管理:用
groups数组存储每组的选中值,确保各组状态互不干扰 - 联动过滤逻辑:姓名下拉框通过
filter方法,根据当前组选中的性别ID筛选对应人员 - 用户体验优化:添加默认提示选项、未选性别时禁用姓名框、切换性别自动清空已选姓名
- 代码规范优化:使用唯一的
Field_ID作为MenuItem的key,避免React警告 - 数据清晰化:整理性别选项为ID+文本的结构,替代原代码中直接显示数字ID的逻辑
内容的提问来源于stack exchange,提问作者Rohit Verma
相关产品推荐
相关产品推荐

